通过修改Laravel Auth使用salt和password进行认证用户(2)

/** * Handle a login request to the application. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function login(Request $request) { $this->validateLogin($request); $throttles = $this->isUsingThrottlesLoginsTrait(); if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return $this->sendLockoutResponse($request); } $credentials = $this->getCredentials($request); if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) { return $this->handleUserWasAuthenticated($request, $throttles); } if ($throttles && ! $lockedOut) { $this->incrementLoginAttempts($request); } return $this->sendFailedLoginResponse($request); }

登录验证的主要操作是在Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'));这个方法调用中来进行的,Auth::guard($this->getGuard()) 获取到的是\Illuminate\Auth\SessionGuard (具体如何获取的看Auth这个Facade \Illuminate\Auth\AuthManager里的源码)

看一下SessionGuard里attempt 方法是如何实现的:

public function attempt(array $credentials = [], $remember = false, $login = true) { $this->fireAttemptEvent($credentials, $remember, $login); $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); if ($this->hasValidCredentials($user, $credentials)) { if ($login) { $this->login($user, $remember); } return true; } if ($login) { $this->fireFailedEvent($user, $credentials); } return false; } /** * Determine if the user matches the credentials. * * @param mixed $user * @param array $credentials * @return bool */ protected function hasValidCredentials($user, $credentials) { return ! is_null($user) && $this->provider->validateCredentials($user, $credentials); }

retrieveByCredentials是用传递进来的字段从数据库中取出用户数据的,validateCredentials是用来验证密码是否正确的实际过程。

这里需要注意的是$this->provider这个provider是一个实现了\Illuminate\Contracts\Auth\UserProvider类的provider, 我们看到目录Illuminate\Auth下面有两个UserProvider的实现,分别为DatabaseUserProvider和EloquentUserProvider, 但是我们验证密码的时候是通过那个来验证的呢,看一下auth的配置文件

'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, //这个是driver用的Model ], ],

这里配置的是driver => eloquent , 那么就是通过EloquentUserProvider的retrieveByCredentials来验证的, 这个EloquentUserProvider 是在SessionGuard实例化时被注入进来的, (具体是怎么通过读取auth配置文件, 实例化相应的provider注入到SessionGuard里的请查阅\Illuminate\Auth\AuthManager 里createSessionDriver方法的源代码)

接下来我们继续查看EloquentUserProvider中retrieveByCredentials和validateCredentials方法的实现:

/** * Retrieve a user by the given credentials. * * @param array $credentials * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByCredentials(array $credentials) { if (empty($credentials)) { return; } $query = $this->createModel()->newQuery(); foreach ($credentials as $key => $value) { if (! Str::contains($key, 'password')) { $query->where($key, $value); } } return $query->first(); } /** * Validate a user against the given credentials. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param array $credentials * @return bool */ public function validateCredentials(UserContract $user, array $credentials) { $plain = $credentials['password']; return $this->hasher->check($plain, $user->getAuthPassword()); }

上面两个方法retrieveByCredentials用除了密码以外的字段从数据库用户表里取出用户记录,比如用email查询出用户记录,然后validateCredentials方法就是通过$this->haser->check来将输入的密码和哈希的密码进行比较来验证密码是否正确。

好了, 看到这里就很明显了, 我们需要改成自己的密码验证就是自己实现一下validateCredentials就可以了, 修改$this->hasher->check为我们自己的密码验证规则就可以了。

首先我们修改$user->getAuthPassword()把数据库中用户表的salt和password传递到validateCredentials中
修改App\User.php 添加如下代码

/** * The table associated to this model */ protected $table = 'user';//用户表名不是laravel约定的这里要指定一下

/** * 禁用Laravel自动管理timestamp列 */ public $timestamps = false; /** * 覆盖Laravel中默认的getAuthPassword方法, 返回用户的password和salt字段 * @return type */ public function getAuthPassword() { return ['password' => $this->attributes['password'], 'salt' => $this->attributes['salt']]; }

然后我们在建立一个自己的UserProvider接口的实现,放到自定义的目录中:

新建app/Foundation/Auth/AdminEloquentUserProvider.php

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/6faba2fe0e60111ef693f178066cab55.html