Laravel 登录验证问题
Laravel 登录验证默认是用user模型,这个模型默认在app目录下User.php,如果用默认的模型,数据库必须要有user表,而且还要有相应的字段。看一下这个模型,这是Laravel默认的User
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User 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', ]; }
一:自定义模型表。
1:假设登录数据表是admin。这里修改config目录下的auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' =>[
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' =>[
'driver' =>'eloquent',
'model' => Models\Admin::class, //模型的位置,这里我放在Models目录,laravel默认在app目录下,你可以放在任何目录
],
注意:红色部分是我们新加的
2:建立Admin模型
<?php namespace Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class Admin extends Authenticatable //必须继承这个契约 { use Notifiable; protected $table = 'admin'; //表 protected $primaryKey = 'id'; //主键 public $timestamps = false; protected $fillable = [ 'username', 'password', ]; protected $hidden = [ 'password', ]; }这个模型我们直接复制修改laravel默认的User.php模型即可。注意这里:class User extends Authenticatable,一定要extends Authenticatable
3:控制器调用认证
//调用admin,我们在config/auth.php里的guards,新加的admin,上面第一步 Auth::guard('admin')->attempt(['username' => $username, 'password' => $password]]); //Laravel默认调用user Auth::attempt(['username' => $username, 'password' => $password]]);
这里有一个问题,laravel验证用的是hash,以前很多项目都是MD5,怎么改?
网上普遍实现的一种方法是修改了laravel源码,我们尽量不动它的源码,我们可以用一种更加简单的方法实现,验证我们自己写,验证完以后通过laravel去认证即可。
首先接受到用户提交的数据后,对比用户名和密码是否正确。如果正确获取用户ID,然后通过 loginUsingId 方法认证即可。
Auth::guard('admin')->loginUsingId(4); //默认是user模型,我这里自定义admin模型,假设用户ID为4
loginUsingId 方法还有个设置,loginUsingId登录并 "记住" 给定用户,此时:
Auth::guard('admin')->loginUsingId(4,true);注意:如果加true,此时laravel会做一个update表的操作,laravel会在模型表中加入一串token,字段为:remember_token,默认的user有这个字段,但自己定义的表需要添加这个字段,当然你也可以指定其他字段。在模型表添加即可,我这里在Admin中添加,在上面第2部Admin模型中添加如下方法。
public function getRememberTokenName() { return 'token';//自定义token字段 }
loginUsingId之后,用户就可以登录了,还需注意中间件的问题,如果我们中间件用的是laravel默认的auth,模型表也是laravel默认的。路由中间件写法
//认证后才可以访问
Route::group(['prefix'=>'admin','namespace'=>'Admin','middleware'=>'auth'],function(){
Route::get('/main','MainController@index');
});
如果模型不是user是我们自己定义的,比如我这里是admin,那么应该这样写:
//认证后才可以访问
Route::group(['prefix'=>'admin','namespace'=>'Admin','middleware'=>'auth:admin'],function(){
Route::get('/main','MainController@index');
});
如果没有这一步,自定义Guards不会通过,明明已经登录,但其他页面还是会显示没登录状态。
打开文件:\vendor\laravel\framework\src\Illuminate\Auth\Middleware\Authenticate.php
public function handle($request, Closure $next, ...$guards) { $this->authenticate($guards); return $next($request); }$guards是个变量,我们必须要把自己的模型admin赋值给它,不然$guards默认就是user。
如果页面没有登录,auth默认跳转到login页面。路由里面设置这个页面
Route::group(['prefix'=>'admin','namespace'=>'Admin'],function(){
Route::get('/',function(){//登录界面
return view('admin.public.login');
})->name('login');
当然也可以换成其他的页面,假如你不想用login这个名称,修改app\Exceptions\Handler.php,添加如下代码
use Illuminate\Auth\AuthenticationException;
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
return redirect()->guest(route('add')); //这里改成其他名字,比如add.相应的路由那里也需要修改。
}
获取登录信息:
\Auth::guard('admin')->user(); //获取登录信息 \Auth::guard('admin')->user()->username; //比如获取登录信息的用户名
4:中间件
中间件主要用来过滤和经验,比如有些页面需要登录后才能访问,一般通过中间件检查
Laravel默认的outh处理,中间件在哪来?我们可以看一下中间件配置文件:app\Http\Kernel.php
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
红色部分中间件为:\app\Http\Middleware\RedirectIfAuthenticated.php文件。
public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { return redirect('/home'); } return $next($request); }这是它里面的方法,通过check()检测是否登录,如果没登录返回到/home。
中间件实现前后台登录跳转
刚才我们中间件用的都是auth,用户访问后台需要认证的界面,如果没登录肯定是跳转到后台登录界面。访问前台则跳转到前台登录界面。这时候建议分别用不同的中间件实现。
假设我们要自定义一个AdminAuth的中间件:
执行:
php artisan make:middleware AdminAuth
执行完毕后,可以看到在\app\Http\Middleware,生成了一个AdminAuth.php的文件,我们的一系列判断就可以写在这里,比如是否登录?跳转等。
public function handle($request, Closure $next) { if(Auth::guard('admin')->check()){ //admin模型 登录成功,跳转 }else{ 跳转到登录页 } return $next($request); }
然后再\app\Http\Kernel.php 注册,添加一行
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'admin' => \App\Http\Middleware\AdminAuth::class,'
];
中间件admin就大功告成了