道者编程

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就大功告成了


最新评论:
1楼 广东省深圳市 电信 发表于 2018-06-07 14:40:07
楼主好强
2楼 亚太地区 发表于 2019-03-21 18:02:01
教程很详细, 帮我解决了问题
共有 2 条记录  首页 上一页 下一页 尾页 1
我要评论:

看不清楚