Laravel 5.3 多用户表登录
Laravl5.3多用户表登录
关于Laravel5.2多用户表登录文章传送门:http://iwanli.me/article/42
简介
在底层代码中,Laravel
的认证组件由 guards
和 providers
组成,Guard
定义了用户在每个请求中如何实现认证,例如,Laravel
通过 session
guard来维护 Session
存储的状态、Cookie
以及 token guard,token guard 是认证用户发送请求时带的API token。
Provider
定义了如何从持久化存储中获取用户信息,Laravel
底层支持通过 Eloquent
和数据库查询构建器两种方式来获取用户,如果需要的话,你还可以定义额外的 Provider
。
相对于Laravel5.2
而言,Laravel5.3
在底层代码中做了很多修改,方法更加简洁,这个下面会提到。虽然代码改了很多,但是原理都是一样的,我们只需要重写不同的方法而已。
默认认证
首先我们使用Laravel 5.3提供的开箱即用的认证:
php artisan make:auth
该Artisan命令会生成用户认证所需的路由、视图以及HomeController:
认证的路由也一并生成好了,查看路由文件routes/web.php
,会发现该文件已经被更新:
Auth::routes();
Route::get('/home', 'HomeController@index');
其中Auth::routes()
定义了登录注册及找回密码路由,/home
为用户认证成功后跳转的路由。
验证
接下来我们先实现前台用户登录,也就是Laravel自带的Users用户表登录。通过生成的默认登录认证,已经写好了所有代码,剩下要做的就是使用迁移命令创建用户认证相关表:
php artisan migrate
执行命令后会生成 users
表和 password_resets
表,分别为用户表和密码重置表。然后我们就可以在浏览器中输入http://blog.me/register来注册新用户:
我们创建一个 iwanli 的用户,注册成功后直接跳转 /home
,并且刚注册的用户名也已经显示出来了:
登录、找回密码功能都已经写好,我就不一一测试了~
自定义用户表登录
首先要看看默认的用户认证配置文件auth.php,配置如下:
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
],
];
认证是由 guard
和 provider
两部分构成的(参考用户认证文档),defaults
配置是选择哪一个 guard 认证驱动,所以我们在这两个配置项中分别添加一个 admin
和 admins
选项。
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
],
];
创建后台用户用户表及Model
接下来我们来实现后台用户登录,使用如下Artisan命令生成后台用户Model:
php artisan make:model Models/Admin -m
带上-m 选项会生成对应迁移文件 *_create_admins_table
,我们定义该数据表字段和users一样,你也可以自定义:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAdminsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('admins', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('admins');
}
}
由于后台一般只需要登录功能,所以来给 admins
表填充一些数据:
php artisan make:seeder AdminsTableSeeder
执行完命令后将会在 database/seeds
目录下生成 AdminsTableSeeder.php
文件。接下来我们定义一个数据模型工厂,在 database/factories/ModelFactory.php
中添加如下代码:
<?php
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/
$factory->define(App\User::class, function (Faker\Generator $faker) {
static $password;
return [
'name' => $faker->name,
'email' => $faker->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'remember_token' => str_random(10),
];
});
$factory->define(App\Models\Admin::class, function (Faker\Generator $faker) {
static $password;
return [
'name' => $faker->name,
'email' => $faker->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'remember_token' => str_random(10),
];
});
模型工厂定义完成后,在 AdminsTableSeeder.php
中填充数据:
<?php
use Illuminate\Database\Seeder;
class AdminsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory('App\Models\Admin',3)->create([
'password' => bcrypt('123456')
]);
}
}
填充数据弄好后,在 DatabaseSeeder.php
中加入 AdminsTableSeeder
类
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// $this->call(UsersTableSeeder::class);
$this->call(AdminsTableSeeder::class);
}
}
最后执行迁移命令:
php artisan migrate --seed
OK,我们在查看数据库:
修改Admin模型类如下:
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
后台用户认证路由及控制器
使用Artisan命令创建控制器:
php artisan make:controller Admin/LoginController
php artisan make:controller Admin/DashboardController
编辑 Admin/LoginController.php
,代码如下:
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login / registration.
*
* @var string
*/
protected $redirectTo = '/admin/dash';
protected $username;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest:admin', ['except' => 'logout']);
$this->username = config('admin.global.username');
}
/**
* 重写登录视图页面
* @author 晚黎
* @date 2016-09-05T23:06:16+0800
* @return [type] [description]
*/
public function showLoginForm()
{
return view('admin.login.index');
}
/**
* 自定义认证驱动
* @author 晚黎
* @date 2016-09-05T23:53:07+0800
* @return [type] [description]
*/
protected function guard()
{
return auth()->guard('admin');
}
}
在 LoginController
中我们在构造函数中修改了 guest
中间件,用来跳转不同路由:
- app\Http\Middleware\RedirectIfAuthenticated.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
// 根据不同 guard 跳转到不同的页面
$url = $guard ? 'admin/dash':'/home';
return redirect($url);
}
return $next($request);
}
}
编辑 Admin/DashboardController.php
,代码如下:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class DashboardController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth.admin:admin');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
dd('后台首页,当前用户名:'.auth('admin')->user()->name);
}
}
在 DashboardController
构造函数中我们添加了一个 auth.admin
Middleware
,这个是我们自定义的,所以我们要来新建一个 Middleware
:
php artisan make:middleware AdminAuthMiddleware
编辑 AdminAuthMiddleware
:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class AdminAuthMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next,$guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('admin/login');
}
}
return $next($request);
}
}
在 app\Http\Kernel.php
中注册:
protected $routeMiddleware = [
......
'auth.admin' => \App\Http\Middleware\AdminAuthMiddleware::class,
......
];
在 routes/web.php
中添加如下路由:
Route::group(['prefix' => 'admin','namespace' => 'Admin'],function ($router)
{
$router->get('login', 'LoginController@showLoginForm')->name('admin.login');
$router->post('login', 'LoginController@login');
$router->post('logout', 'LoginController@logout');
$router->get('dash', 'DashboardController@index');
});
视图文件创建及修改
最后我们要创建后台用户认证对应视图文件,这里我们简单复制默认用户视图模板并稍作修改即可,复制 resources\views\auth\login.blade.php
文件到并重命名 resources\views\admin\login\index.blade.php
。
修改resources\views\admin\login\index.blade.php
目录下登录及注册表单提交地址:
{{ url('/login') }} -> {{ route('admin.login') }}
OK,在浏览器中访问http://blog.me/admin/login
测试:
点击login,页面跳转到http://blog.me/admin/dash
,说明后台登录成功!
OK,至此我们已经完成前后台用户同时登录认证功能。 Enjoy it !
更多关于Laravel的文章请关注我的博客:http://www.iwanli.me
这是 5.3 默认的登录注册页面 UI 吗?阿黎
@Summer 恩 默认的
@lanceWan 感谢分享这么高质量的文章,对于新手与我来讲都有很大的帮助,感谢!另外帮忙改了一处:routes\web.php -> routes/web.php, 加油!
@overtrue :smile: 非常感谢~
大赞
这篇文章对新手很有学习参考价值 :+1:
很厉害,写的这么详细。:+1:
犹如行云流水一般,楼主博客好漂亮
标题错别字 ->
Laravl5.3
我已经改过来,博客的你自己改哈@Summer 。。。。。看来每次写完要查几次错别字了
@lanceWan 哈哈,没事,这种事情经常发生
还是放一起的好,最好不好区分
:+1:
:punch: 非常有价值!
直接用users表然后给权限不就行了吗
@ilhamxyz 方法有很多种,这只是其中的一种方案。
阿黎,我是完全按照你的这个流程写的,到最后点击登录提交的时候,提示我页面无法运作,没有做跳转,还停留在admin/login,能大概知道是什么原因吗?
@DolphinBay 没有截图看看? 这个我也不好直接说哪里问题呀
@lanceWan 刚才的问题是我写错了一个地方,但是又遇到一个问题就是,点击登录以后确实能跳转到,admin/dash 但是会提示页面无法运作,代码追到AdminAuthMiddleware.php中的handle,就挂掉了。 我按照图片的写法,就可以了。 什么愿意呢?
@DolphinBay Auth是门面,必须
use Auth
一下才能用 ,或者想你那样加个\
就可以了 。或者你还可以用辅助函数auth($guard)->guest()
也是一样的效果@lanceWan 非常感谢,已经应用到项目中了。虽然还有个别地方不理解。
@lanceWan 在修改Admin模型那里,use了这个类,我不能理解,是否可以解释一下?卡在这里好久了
use Illuminate\Foundation\Auth\User as Authenticatable;
还下面的继承关系
class Admin extends Authenticatable
博主写的非常赞
@lanceWan 还有一个问题请教一下,如果我没有登陆,范文会自动跳转到 XX.com/admin/login, 但是我登陆了以后, 在去访问 xx.com/admin/login,就会跳转到, xx.com/admin/dash 。然后报错,报的是没有admin/dash路由的问题,可是我登陆成功明显跳转的不是这个路由,而且 ,我的代码里面根本就没有 dash 这个关键字,是个是为什么啊 ?
@ChenPHPER
class Admin extends Authenticatable
这个之所以要继承这个类,是因为Laravel认证驱动会检查你的Model必须继承这个类 ,不然会报错。Authenticatable
实质上还是继承model的,只不过多了一些方法还有个问题,use Illuminate\Foundation\Auth\User as Authenticatable;在这里,我model里面是没有User这个模型的,相对应的用户的是Member,这个需要修改什么吗?
@ChenPHPER 我想你理解错了,这个User并不是你认为的users表,代表的是用户管理吧。这是Laravel的源码:
源码里面实质还是继承model,只不过实现了一些接口而已。实现接口方法由
Authenticatable, Authorizable, CanResetPassword
这三个Trait
实现,分别处理认证用户,修改密码之类的。所以你不用修改任何东西,只要你继承就行@lanceWan ok,明白了。我之前只看了下api文档,没搞明白,现在点通了,谢谢哈~不过我们不是基于jwt认证的吗?为什么还要用laravel底层的东西去实现?
博主我复制login.blade.php文件后改名为admin目录下login目录下的index.blade.app后访问页面就会报$error这个全局变量没定义,而访问login.blade.php却没有报这个错
附上报错的图
@王杰 这个可能是session的问题,你的路由加了中间件web没? 试一下
@lanceWan 是添加路由的时候没有在web中间件加,不能处理$error全局变量,现在好了,谢啦!!☆⌒(*^-゜)v
请问LoginController中的自定义认证驱动是什么作用?
@shawn 这是指定
config/auth.php
中的用那个providers进行认证 默认是使用users
的provider@lanceWan 就是说这个跟在控制器构造函数中指定是一样的作用是吧
@shawn 恩 这个中间件也是指定配置中的驱动
php artisan make:controller Admin/LgoinController
的单词拼写错了
应该是:
···
php artisan make:controller Admin/LoginController
···
logout的时候为什么直接跳转到 前台的首页,而且后台注销后前台也注销了,前台注销后台也注销了,怎么修改才能前后台各自可以注销
@周军 谢谢 原谅总打错字:smile:
@JINJIALEI 注销这个问题的话我还没仔细去看Laravel的方法,有时间我去仔细看看有什么方法解决
参考您的文章,进行了拓展,教程:Laravel5.3 多表验证(包括登录注册,找回密码,发送邮件) 里边提到了您的文章,感觉不妥的话可以联系我~
@贺钧威 没有什么不妥的,对你有帮助就行了~
错别字 创建后台login控制器命令的 打错字了
@xhh110 这个很尴尬,之前有人跟我说了 。 你们知道就行,我就不多说了~~:smile:
@lanceWan 可以改一下嘛
@xhh110 OK,改好了
@lanceWan 在blade模板中。。。Auth::User()->name 获取到前台用户名称 后台怎么获取呢??
还有 Auth::guest() 怎么认证后台的呢???
@lanceWan
为什么Auth::user()取不到数据?
你这样做了后,用户数据存在哪里,session中也没有
@xhh110
@黄爽 要先指定 guard(非 default 的)用
Auth::guard('admin')->user()
@qqjt 这个我会了。就是attempt不能通过无密码认证。。。只能用setLoginId() 来实现我想要的了、。。
不错,实践成功!
收藏
发现一个不知道算不算问题的问题,
就是如果同时登录了多个用户(不同表),只要其中一个用户退出,所有用户都退出了,,
注释掉
AuthenticatesUsers
中logout
方法里的$request->session()->invalidate();
这一行,可以只退出你要退出的用户,就是不知道有没有什么后遗症?或者有没有方法可以清除特定guard的session?
望大佬解答~~
@largezhou
$request->session()->forget('xx')
就可以了前台和后台session信息该怎么区分呀
我今天研究了下,感觉还是挺麻烦。假如一个系统分前台后台,甚至有些还有第三种类型,操作起来就挺麻烦。laravel这个适合一个应用只做一种身份认证。