第一步需要配置Laravel的email功能,此外还需要在数据库中创建一个新表password_resets来存储用户的email和对应的token
CREATE TABLE `password_resets` (
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`token` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
KEY `password_resets_email_index` (`email`),
KEY `password_resets_token_index` (`token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
通过重置密码表单的提交地址可以看到,表单把新的密码用post提交给了/password/reset,我们先来看一下auth相关的路由,确定/password/reset对应的控制器方法。
$this->post('password/reset', 'Auth\PasswordController@reset');
可以看到对应的控制器方法是\App\Http\Controllers\Auth\PasswordController类的reset方法,这个方法实际是定义在\Illuminate\Foundation\Auth\ResetsPasswords 这个traits里,PasswordController引入了这个traits
/**
* Reset the given user's password.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function reset(Request $request)
{
$this->validate(
$request,
$this->getResetValidationRules(),
$this->getResetValidationMessages(),
$this->getResetValidationCustomAttributes()
);
$credentials = $this->getResetCredentials($request);
$broker = $this->getBroker();
$response = Password::broker($broker)->reset($credentials, function ($user, $password) {
$this->resetPassword($user, $password);
});
switch ($response) {
case Password:ASSWORD_RESET:
return $this->getResetSuccessResponse($response);
default:
return $this->getResetFailureResponse($request, $response);
}
}
方法开头先通过validator对输入进行验证,接下来在程序里传递把新密码和一个闭包对象传递给Password::broker($broker)->reset();方法,这个方法定义在\Illuminate\Auth\Passwords\PasswordBroker类里.
/**
* Reset the password for the given token.
*
* @param array $credentials
* @param \Closure $callback
* @return mixed
*/
public function reset(array $credentials, Closure $callback)
{
// If the responses from the validate method is not a user instance, we will
// assume that it is a redirect and simply return it from this method and
// the user is properly redirected having an error message on the post.
$user = $this->validateReset($credentials);
if (! $user instanceof CanResetPasswordContract) {
return $user;
}
$pass = $credentials['password'];
// Once we have called this callback, we will remove this token row from the
// table and return the response from this callback so the user gets sent
// to the destination given by the developers from the callback return.
call_user_func($callback, $user, $pass);
$this->tokens->delete($credentials['token']);
return static:ASSWORD_RESET;
}
在PasswordBroker的reset方法里,程序会先对用户提交的数据做再一次的认证,然后把密码和用户实例传递给传递进来的闭包,在闭包调用里完成了将新密码更新到用户表的操作, 在闭包里程序调用了的PasswrodController类的resetPassword方法
function ($user, $password) {
$this->resetPassword($user, $password);
});
PasswrodController类resetPassword方法的定义
protected function resetPassword($user, $password)
{
$user->forceFill([
'password' => bcrypt($password),
'remember_token' => Str::random(60),
])->save();
Auth::guard($this->getGuard())->login($user);
}
在这个方法里Laravel 用的是bcrypt 加密了密码, 那么要改成我们需要的salt + password的方式,我们在PasswordController类里重写resetPassword方法覆盖掉traits里的该方法就可以了。
/**
* 覆盖ResetsPasswords traits里的resetPassword方法,改为用sha1(salt + password)的加密方式
* Reset the given user's password.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @param string $password
* @return void
*/
protected function resetPassword($user, $password)
{
$salt = Str::random(6);
$user->forceFill([
'password' => sha1($salt . $password),
'salt' => $salt,
'remember_token' => Str::random(60),
])->save();
\Auth::guard($this->getGuard())->login($user);
} 结语
到这里对Laravel Auth的自定义就完成了,注册、登录和重置密码都改成了sha1(salt + password)的密码加密方式, 所有自定义代码都是通过定义Laravel相关类的子类和重写方法来完成没有修改Laravel的源码,这样既保持了良好的可扩展性也保证了项目能够自由迁移。 注:使用的Laravel版本为5.2 总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。