將 Laravel 使用者密碼加密方式修改為 md5+salt 方式

bossaiguo發表於2019-01-30

總以為已經過了見一個愛一個的年紀,直到我遇見了。。。。

以前公司一直是使用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的使用者認證系統加入到你的專案中啦!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章