PHP实战:通过修改Laravel Auth使用salt和password进行认证用户详解
|
《PHP实战:通过修改Laravel Auth使用salt和password进行认证用户详解》要点: 前言 本文主要给大家介绍了通过修改Laravel Auth用salt和password进行认证用户的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍:PHP编程 Laraval自带的用户认证系统Auth非常强大易用,不过在Laravel的用户认证系统中用户注册、登录、找回密码这些模块中用到密码加密和认证算法时使用的都是bcrypt,而很多之前做的项目用户表里都是采用存储salt + password加密字符串的方式来记录用户的密码的,这就给使用Laravel框架来重构之前的项目带来了很大的阻力,不过最近自己通过在网上找资料、看社区论坛、看源码等方式完成了对Laravel Auth的修改,在这里分享出来希望能对其他人有所帮助. 开篇之前需要再说明下如果是新项目应用Laravel框架,那么不需要对Auth进行任何修改,默认的bcrypt加密算法是比salt + password更安全更高效的加密算法.PHP编程 修改用户注册 首先,在laravel 里启用验证是用的artisan命令PHP编程 php artisan make:auth 执行完命令后在routes文件(位置:app/Http/routes.php)会多一条静态方法调用PHP编程 Route::auth(); 这个Route是Laravel的一个Facade (位于IlluminateSupportFacadesRoute),调用的auth方法定义在IlluminateRoutingRouter类里,如下可以看到auth方法里就是定义了一些Auth相关的路由规则PHP编程
/**
* Register the typical authentication routes for an application.
*
* @return void
*/
public function auth()
{
// Authentication Routes...
$this->get('login','AuthAuthController@showLoginForm');
$this->post('login','AuthAuthController@login');
$this->get('logout','AuthAuthController@logout');
// Registration Routes...
$this->get('register','AuthAuthController@showRegistrationForm');
$this->post('register','AuthAuthController@register');
// Password Reset Routes...
$this->get('password/reset/{token?}','AuthPasswordController@showResetForm');
$this->post('password/email','AuthPasswordController@sendResetLinkEmail');
$this->post('password/reset','AuthPasswordController@reset');
}
通过路由规则可以看到注册时请求的控制器方法是AuthController的register方法,该方法定义在IlluminateFoundationAuthRegistersUsers这个traits里,AuthController在类定义里引入了这个traits.PHP编程
/**
* Handle a registration request for the application.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
public function register(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request,$validator
);
}
Auth::guard($this->getGuard())->login($this->create($request->all()));
return redirect($this->redirectPath());
}
在register方法里首先会对request里的用户输入数据进行验证,你只需要在AuthController的validator方法里定义自己的每个输入字段的验证规则就可以PHP编程
protected function validator(array $data)
{
return Validator::make($data,[
'name' => 'required|max:255','email' => 'required|email|max:255|unique:user','password' => 'required|size:40|confirmed',]);
}
接着往下看验证通过后,Laravel会掉用AuthController的create方法来生成新用户,然后拿着新用户的数据去登录 所以我们要自定义用户注册时生成用户密码的加密方式只需要修改AuthController的create方法即可. 比如:PHP编程
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return User
*/
protected function create(array $data)
{
$salt = Str::random(6);
return User::create([
'nickname' => $data['name'],'email' => $data['email'],'password' => sha1($salt . $data['password']),'register_time' => time(),'register_ip' => ip2long(request()->ip()),'salt' => $salt
]);
}
修改用户登录 修改登录前我们需要先通过路由规则看一下登录请求的具体控制器和方法,在上文提到的auth方法定义里可以看到PHP编程
$this->get('login','AuthAuthController@logout');
验证登录的操作是在AppHttpControllersAuthAuthController类的login方法里.打开AuthController发现Auth相关的方法都是通过性状(traits)引入到类内的,在类内use 要引入的traits,在编译时PHP就会把traits里的代码copy到类中,这是PHP5.5引入的特性具体适用场景和用途这里不细讲. 所
/**
* Handle a login request to the application.
*
* @param IlluminateHttpRequest $request
* @return IlluminateHttpResponse
*/
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);
}
登录验证的主要操作是在 看一下SessionGuard里attempt 方法是如何实现的:PHP编程
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是用来验证密码是否正确的实际过程.PHP编程 这里需要注意的是 'providers' => [ 'users' => [ 'driver' => 'eloquent','model' => AppUser::class,//这个是driver用的Model ],], 这里配置的是 接下来我们继续查看EloquentUserProvider中retrieveByCredentials和validateCredentials方法的实现:PHP编程
/**
* Retrieve a user by the given credentials.
*
* @param array $credentials
* @return IlluminateContractsAuthAuthenticatable|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 IlluminateContractsAuthAuthenticatable $user
* @param array $credentials
* @return bool
*/
public function validateCredentials(UserContract $user,array $credentials)
{
$plain = $credentials['password'];
return $this->hasher->check($plain,$user->getAuthPassword());
}
(编辑:鄂州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
