将 Laravel 用户密码加密方式修改为 md5+salt 方式

总以为已经过了见一个爱一个的年纪,直到我遇见了。。。。

以前公司一直是使用phpcms框架,但由于种种原因(百度上搜索‘phpcms’的第一个词条是“倒闭了”??),公司现在需要对项目进行 重架构。数据表、业务逻辑基本不变,就是把phpcms框架换成最优雅的php框架 ——— laravel

laravel好用是好用,而且已经封装好了一套用户验证系统,可谓是爽歪歪。问题就出在他的密码加密方式是固定的,和phpcms 的MD5+salt 可谓天壤之别。。。

通过源码追踪我们可以知道laravel 密码验证方式
在 vendor/laravel/src/Illuminate/src/Auth/EloquentUserProvider 类中:

public function validateCredentials(UserContract $user, array $credentials)
{
    $plain = $credentials['password'];
    return $this->hasher->check($plain, $user->getAuthPassword());
}

我们只要自定义用户提供器就能实现自定义密码加密方式

首先我们来重写$user->getAuthPassword(); 在User模型中覆盖其从父类中继承来的这个方法,把数据库中用户表的salt和password传递到validateCredentials中来:

class user extends Authenticatable
{
    /**
     * 覆盖Laravel中默认的getAuthPassword方法, 返回用户的password和salt字段
     * @return array
     */
    public function getAuthPassword()
    {
        return ['password' => $this->attributes['password'], 'salt' => $this->attributes['salt']];
    }
} 

然后我们用一个自定义的用户提供器,通过它的validateCredentials来实现我们自己系统的密码验证规则,由于用户提供器的其它方法不用改变沿用EloquentUserProvider里的实现就可以,所以我们让自定义的用户提供器继承自EloquentUserProvider:

namespace App\Libs;

use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Str;

class SelfEloquentUserProvider extends EloquentUserProvider
{

    /**
     * Validate a user against the given credentials.
     *
     * @param \Illuminate\Contracts\Auth\Authenticatable $user
     * @param array $credentials
     */
    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        $plain = $credentials['password'];
        $authPassword = $user->getAuthPassword();
        //这里你可以根据你的业务需求,自定义加密方式。我这个位置是使用phpcms的加密方式。
        return md5(md5(trim($plain)).$authPassword['salt']) == $authPassword['password'];
    }
}

接下来通过Auth::provider()将CustomEloquentUserProvider注册到Laravel系统中,Auth::provider方法将一个返回用户提供器对象的闭包作为用户提供器创建器以给定名称注册到Laravel中,代码如下:

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        \Auth::provider('self-eloquent', function ($app, $config) {
            return New \App\Libs\SelfEloquentUserProvider($app['hash'], $config['model']);
        });
    }
    ......
}

注册完用户提供器后我们就可以在config/auth.php里配置让看守器使用新注册的self-eloquent作为用户提供器了:

//config/auth.php
'providers' => [
    'users' => [
        'driver' => 'self-eloquent',
        'model' => \App\User::class,
    ]
]

大功告成,到了这一步你就可以无缝地将laravel的用户认证系统加入到你的项目中啦!

php
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 5

@shufeng 我的也是jwt+dingo,你按我上面说的,自定义一个用户提供器。

5年前 评论

非常感谢,这两天就纠结于这个密码加密方式的问题,我的也是phpcms的老后台重构 :joy:

4年前 评论

过程清晰,亲测有效,👍

3年前 评论

如果用户表的用户名是 user_name 密码字段是 user_psd 这个要怎么改?我按照你的步骤还是不行,不知道是不是字段名字不同导致

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!