鍍金池/ 教程/ PHP/ 用戶認(rèn)證
門面
Laravel Homestead
安裝及配置
測試
HTTP 中間件
加密
升級(jí)指南
幫助函數(shù)
應(yīng)用目錄結(jié)構(gòu)
集合
新手入門指南-簡單任務(wù)管理系統(tǒng)
任務(wù)調(diào)度
查詢構(gòu)建器
視圖
驗(yàn)證
Laravel Cashier(訂購&支付&發(fā)票)
本地化
隊(duì)列
調(diào)整器
分頁
文件系統(tǒng)/云存儲(chǔ)
貢獻(xiàn)代碼
哈希
HTTP 控制器
緩存
遷移
HTTP 請求
Laravel Elixir
發(fā)行版本說明
Envoy 任務(wù)運(yùn)行器(SSH任務(wù))
序列化
Session
起步
帶用戶功能的任務(wù)管理系統(tǒng)
起步
用戶授權(quán)
郵件
事件
填充數(shù)據(jù)
HTTP 路由
服務(wù)提供者
Blade 模板引擎
包開發(fā)
用戶認(rèn)證
Artisan 控制臺(tái)
HTTP 響應(yīng)
集合
服務(wù)容器
關(guān)聯(lián)關(guān)系
一次請求的生命周期
契約
Redis
錯(cuò)誤&日志

用戶認(rèn)證

1、簡介

Laravel 中實(shí)現(xiàn)用戶認(rèn)證非常簡單。實(shí)際上,幾乎所有東西都已經(jīng)為你配置好了。配置文件位于 config/auth.php,其中包含了用于調(diào)整認(rèn)證服務(wù)行為的文檔友好的選項(xiàng)配置。

1.1 數(shù)據(jù)庫考量

默認(rèn)情況下,Laravel 在 app 目錄下包含了一個(gè) Eloquent 模型 App\User,這個(gè)模型可以和默認(rèn)的 Eloquent 認(rèn)證驅(qū)動(dòng)一起使用。如果你的應(yīng)用不使用 Eloquent,你可以使用 database 認(rèn)證驅(qū)動(dòng),該驅(qū)動(dòng)使用了 Laravel 查詢構(gòu)建器。

App\User 模型構(gòu)建數(shù)據(jù)庫表結(jié)構(gòu)的時(shí)候,確保 password 字段長度至少有 60 位。

還有,你應(yīng)該驗(yàn)證 users 表包含了可以為空的、字符串類型的 remember_token 字段長度為 100,該字段用于存儲(chǔ)被應(yīng)用維護(hù)的”記住我(remember me)“的 session 令牌,這可以通過在遷移中使用$table->rememberToken();來實(shí)現(xiàn)。

2、用戶認(rèn)證快速入門

Laravel 處理兩個(gè)認(rèn)證控制器,位于 App\Http\Controllers\Auth命名空間下,AuthController 處理新用戶注冊和認(rèn)證,PasswordController 包含幫助用戶找回密碼的邏輯。每個(gè)控制器都使用 trait 來引入它們需要的方法。對很多應(yīng)用而言,你根本不需要修改這兩個(gè)控制器。

2.1 路由

默認(rèn)情況下,沒有路由將請求指向用戶認(rèn)證控制器,你要手動(dòng)在 app/Http/routes.php 文件中添加它們:

// 認(rèn)證路由...
Route::get('auth/login', 'Auth\AuthController@getLogin');
Route::post('auth/login', 'Auth\AuthController@postLogin');
Route::get('auth/logout', 'Auth\AuthController@getLogout');
// 注冊路由...
Route::get('auth/register', 'Auth\AuthController@getRegister');
Route::post('auth/register', 'Auth\AuthController@postRegister');

2.2 視圖

盡管框架包含了用戶認(rèn)證控制器,你還是需要提供這些控制器可以渲染的視圖。這些視圖位于 resources/views/auth 目錄,你可以按需自定義這些視圖文件。登錄視圖是 resources/views/auth/login.blade.php,注冊視圖是 resources/views/auth/register.blade.php。

2.2.1 登錄表單示例

<!-- resources/views/auth/login.blade.php -->

<form method="POST" action="/auth/login">
    {!! csrf_field() !!}

    <div>
        Email
        <input type="email" name="email" value="{{ old('email') }}">
    </div>

    <div>
        Password
        <input type="password" name="password" id="password">
    </div>

    <div>
        <input type="checkbox" name="remember"> Remember Me
    </div>

    <div>
        <button type="submit">Login</button>
    </div>
</form>

2.2.2 注冊表單示例

<!-- resources/views/auth/register.blade.php -->

<form method="POST" action="/auth/register">
    {!! csrf_field() !!}

    <div>
        Name
        <input type="text" name="name" value="{{ old('name') }}">
    </div>

    <div>
        Email
        <input type="email" name="email" value="{{ old('email') }}">
    </div>

    <div>
        Password
        <input type="password" name="password">
    </div>

    <div>
        Confirm Password
        <input type="password" name="password_confirmation">
    </div>

    <div>
        <button type="submit">Register</button>
    </div>
</form>

2.3 認(rèn)證

既然你已經(jīng)為自帶的認(rèn)證控制器設(shè)置好了路由和視圖,接下來就準(zhǔn)備為應(yīng)用注冊新用戶并進(jìn)行登錄認(rèn)證。你可以在瀏覽器中訪問定義好的路由,認(rèn)證控制器已經(jīng)實(shí)現(xiàn)了認(rèn)證已存在用戶以及存儲(chǔ)新用戶到數(shù)據(jù)庫中的業(yè)務(wù)邏輯(通過 trait)。

當(dāng)一個(gè)用戶成功進(jìn)行登錄認(rèn)證后,將會(huì)跳轉(zhuǎn)到/home 鏈接,你需要事先注冊一個(gè)路由來處理該跳轉(zhuǎn)。你可以通過在 AuthController 中設(shè)置 redirectPath 屬性來自定義 post 認(rèn)證之后的跳轉(zhuǎn)路徑:

protected $redirectPath = '/dashboard';

當(dāng)一個(gè)用戶登錄認(rèn)證失敗后,將會(huì)跳轉(zhuǎn)到 /auth/login 鏈接。你可以通過定義 AuthControllerloginPath 屬性來自定義 post 認(rèn)證失敗后的跳轉(zhuǎn)路徑:

protected $loginPath = '/login';

2.3.1 自定義

要修改新用戶注冊所必需的表單字段,或者自定義新用戶字段如何存儲(chǔ)到數(shù)據(jù)庫,你可以修改 AuthController 類。該類負(fù)責(zé)為應(yīng)用驗(yàn)證和創(chuàng)建新用戶。

AuthControllervalidator 方法包含了新用戶的驗(yàn)證規(guī)則,你可以隨意按需要自定義該方法。

AuthControllercreate 方法負(fù)責(zé)使用 Eloquent ORM在數(shù)據(jù)庫中創(chuàng)建新的 App\User 記錄。你可以基于自己的需要隨意自定義該方法。

2.4 獲取認(rèn)證用戶

你可以通過 Auth 門面訪問認(rèn)證用戶:

$user = Auth::user();

一旦用戶通過認(rèn)證后,你還可以通過 Illuminate\Http\Request 實(shí)例訪問認(rèn)證用戶:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class ProfileController extends Controller{
    /**
     * 更新用戶屬性.
     *
     * @param  Request  $request
     * @return Response
     */
    public function updateProfile(Request $request)
    {
        if ($request->user()) {
            // $request->user() 返回認(rèn)證用戶實(shí)例...
        }
    }
}

2.4.1 判斷當(dāng)前用戶是否通過認(rèn)證

要判斷某個(gè)用戶是否登錄到應(yīng)用,可以使用 Auth 門面的 check 方法,如果用戶通過認(rèn)證則返回 true

if (Auth::check()) {
    // The user is logged in...
}

此外,你還可以在用戶訪問特定路由/控制器之前使用中間件來驗(yàn)證用戶是否通過認(rèn)證,想要了解更多,可以查看路由保護(hù)文檔。

2.5 路由保護(hù)

路由中間件可用于只允許通過認(rèn)證的用戶訪問給定路由。Laravel 通過定義在 app\Http\Middleware\Authenticate.phpauth 中間件來處理這一操作。你所要做的僅僅是將該中間件加到相應(yīng)的路由定義中:

// 使用路由閉包...
Route::get('profile', ['middleware' => 'auth', function() {
    // 只有認(rèn)證用戶可以進(jìn)入...
}]);
// 使用控制器...
Route::get('profile', [
    'middleware' => 'auth',
    'uses' => 'ProfileController@show'
]);

當(dāng)然,如果你正在使用控制器類,也可以在控制器的構(gòu)造方法中調(diào)用 middleware 方法而不是在路由器中直接定義:

public function __construct(){
    $this->middleware('auth');
}

2.6 登錄失敗次數(shù)限制

如果你正在使用 Laravel 內(nèi)置的 AuthController 類,Illuminate\Foundation\Auth\ThrottlesLogins trait 可以用于限制用戶登錄失敗次數(shù)。默認(rèn)情況下,用戶在幾次登錄失敗后將在一分鐘內(nèi)不能登錄,這種限制基于用戶的用戶名/郵箱地址+IP 地址:

<?php

namespace App\Http\Controllers\Auth;

use App\User;use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;

class AuthController extends Controller{
    use AuthenticatesAndRegistersUsers, ThrottlesLogins;

    // AuthController 類的其它部分...
}

3、手動(dòng)認(rèn)證用戶

當(dāng)然,你也可以不使用 Laravel 自帶的認(rèn)證控制器。如果你選擇移除這些控制器,你需要直接使用 Laravel 認(rèn)證類來管理用戶認(rèn)證。別擔(dān)心,這很簡單!

我們將會(huì)通過 Auth 門面來訪問認(rèn)證服務(wù),因此我們需要確保在類的頂部導(dǎo)入了 Auth門面,讓我們看看 attempt 方法:

<?php

namespace App\Http\Controllers;

use Auth;
use Illuminate\Routing\Controller;

class AuthController extends Controller{
    /**
     * 處理登錄認(rèn)證
     *
     * @return Response
     */
    public function authenticate()
    {
        if (Auth::attempt(['email' => $email, 'password' => $password])) {
            // 認(rèn)證通過...
            return redirect()->intended('dashboard');
        }
    }
}

attempt 方法接收鍵值數(shù)組對作為第一個(gè)參數(shù),數(shù)組中的值被用于從數(shù)據(jù)表中查找用戶,因此,在上面的例子中,用戶將會(huì)通過 email 的值獲取,如果用戶被找到,經(jīng)哈希運(yùn)算后存儲(chǔ)在數(shù)據(jù)中的密碼將會(huì)和傳遞過來的經(jīng)哈希運(yùn)算處理的密碼值進(jìn)行比較。如果兩個(gè)經(jīng)哈希運(yùn)算的密碼相匹配那么一個(gè)認(rèn)證 session 將會(huì)為這個(gè)用戶開啟。

如果認(rèn)證成功的話 attempt 方法將會(huì)返回 true。否則,返回 false。 重定向器上的 intended 方法將會(huì)將用戶重定向到登錄之前用戶想要訪問的 URL,在目標(biāo) URL 無效的情況下備用 URI 將會(huì)傳遞給該方法。 如果你想的話,除了用戶郵件和密碼之外還可以在認(rèn)證查詢時(shí)添加額外的條件,例如,我們可以驗(yàn)證被標(biāo)記為有效的用戶:

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
    // The user is active, not suspended, and exists.
}

要退出應(yīng)用,可以使用 Auth 門面的 logout 方法,這將會(huì)清除用戶 session 中的認(rèn)證信息:

Auth::logout();

注意:在這些例子中,email 并不是必須選項(xiàng),在這里只不過是作為一個(gè)例子。你可以在自己的數(shù)據(jù)庫使用任何其他與“用戶名”相對應(yīng)的字段。

3.1 記住用戶

如果你想要在應(yīng)用中提供“記住我”的功能,可以傳遞一個(gè)布爾值作為第二個(gè)參數(shù)到 attempt 方法,這樣用戶登錄認(rèn)證狀態(tài)就會(huì)一直保持直到他們手動(dòng)退出。當(dāng)然,你的 users 表必須包含 remember_token 字段,該字段用于存儲(chǔ)“記住我”令牌。

if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
    // The user is being remembered...
}

如果你要“記住”用戶,可以使用 viaRemember 方法來判斷用戶是否使用“記住我”cookie 進(jìn)行認(rèn)證:

if (Auth::viaRemember()) {
    //
}

3.2 其它認(rèn)證方法

3.2.1 認(rèn)證用戶實(shí)例

如果你需要將一個(gè)已存在的用戶實(shí)例登錄到應(yīng)用中,可以調(diào)用用戶實(shí)例上的 login 方法,給定實(shí)例必須是 Illuminate\Contracts\Auth\Authenticatable契約的實(shí)現(xiàn),當(dāng)然,Laravel 自帶的 App\User 模型已經(jīng)實(shí)現(xiàn)了該接口:

Auth::login($user);

3.2.2 通過 ID 認(rèn)證用戶

要通過用戶 ID 登錄到應(yīng)用,可以使用 loginUsingId 方法,該方法接收你想要認(rèn)證用戶的主鍵作為參數(shù):

Auth::loginUsingId(1);

3.2.3 一次性認(rèn)證用戶

你可以使用 once 方法只在單個(gè)請求中將用戶登錄到應(yīng)用,而不存儲(chǔ)任何 session 和 cookie,這在構(gòu)建無狀態(tài)的 API 時(shí)很有用。once 方法和 attempt 方法用法差不多:

if (Auth::once($credentials)) {
    //
}

4、基于HTTP的基本認(rèn)證

HTTP 基本認(rèn)證能夠幫助用戶快速實(shí)現(xiàn)登錄認(rèn)證而不用設(shè)置專門的登錄頁面,首先要在路由中加上 auth.basic中間件。該中間件是 Laravel自帶的,所以不需要自己定義:

Route::get('profile', ['middleware' => 'auth.basic', function() {
    // 只有認(rèn)證用戶可以進(jìn)入...
}]);

中間件加到路由中后,當(dāng)在瀏覽器中訪問該路由時(shí),會(huì)自動(dòng)提示需要認(rèn)證信息,默認(rèn)情況下,auth.basic 中間件使用用戶記錄上的 email 字段作為“用戶名”。

FastCGI 上注意點(diǎn) 如果你使用 PHP FastCGI,HTTP 基本認(rèn)證將不能正常工作,需要在.htaccess 文件加入如下內(nèi)容:

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

4.1 無狀態(tài)的 HTTP 基本認(rèn)證

使用 HTTP 基本認(rèn)證也不需要在 session 中設(shè)置用戶標(biāo)識(shí) cookie,這在 API 認(rèn)證中非常有用。要實(shí)現(xiàn)這個(gè),需要定義一個(gè)調(diào)用 onceBasic 方法的中間件。如果該方法沒有返回任何響應(yīng),那么請求會(huì)繼續(xù)走下去:

<?php

namespace Illuminate\Auth\Middleware;

use Auth;
use Closure;

class AuthenticateOnceWithBasicAuth{
    /**
     * 處理輸入請求.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return Auth::onceBasic() ?: $next($request);
    }

}

接下來,注冊路由中間件并將其添加到路由中:

Route::get('api/user', ['middleware' => 'auth.basic.once', function() {
    // 只有認(rèn)證用戶可以進(jìn)入...
}]);

5、重置密碼

5.1 數(shù)據(jù)庫考量

大多數(shù) web 應(yīng)用提供了用戶重置密碼的功能,Laravel 提供了便利方法用于發(fā)送密碼提示及執(zhí)行密碼重置而不需要你在每個(gè)應(yīng)用中重新實(shí)現(xiàn)。

開始之前,先驗(yàn)證 App\User 模型實(shí)現(xiàn)了 Illuminate\Contracts\Auth\CanResetPassword 契約。當(dāng)然,Laravel 自帶的 App\User 模型已經(jīng)實(shí)現(xiàn)了該接口,并使用 Illuminate\Auth\Passwords\CanResetPassword trait 來包含實(shí)現(xiàn)該接口需要的方法。

5.1.1 生成重置令牌表遷移

接下來,用來存儲(chǔ)密碼重置令牌的表必須被創(chuàng)建,Laravel 已經(jīng)自帶了這張表的遷移,就存放在 database/migrations 目錄。所有,你所要做的僅僅是運(yùn)行遷移:

php artisan migrate

5.2 路由

Laravel 自帶了 Auth\PasswordController,其中包含重置用戶必須的邏輯。然而,你需要定義一個(gè)路由將請求轉(zhuǎn)發(fā)到該控制器:

// 密碼重置鏈接請求路由...
Route::get('password/email', 'Auth\PasswordController@getEmail');
Route::post('password/email', 'Auth\PasswordController@postEmail');
// 密碼重置路由...
Route::get('password/reset/{token}', 'Auth\PasswordController@getReset');
Route::post('password/reset', 'Auth\PasswordController@postReset');

5.3 視圖

除了為 Auth\PasswordController 定義路由之外,還需要提供相應(yīng)視圖,別擔(dān)心,我們將會(huì)提供示例視圖來幫助你開始,當(dāng)然,你也可以自定義表單樣式。

5.3.1 密碼重置鏈接請求表單示例

你需要為密碼重置請求表單 提供 HTML 視圖,該視圖文件應(yīng)該放在 resources/views/auth/password.blade.php,表單提供了一個(gè)輸入用戶郵箱地址的字段,從而允許用戶從郵件中訪問密碼重置鏈接:

<!-- resources/views/auth/password.blade.php -->

<form method="POST" action="/password/email">
    {!! csrf_field() !!}

    <div>
        Email
        <input type="email" name="email" value="{{ old('email') }}">
    </div>

    <div>
        <button type="submit">
            Send Password Reset Link
        </button>
    </div>
</form>

當(dāng)一個(gè)用戶提交了重置密碼請求后,將會(huì)收到一封電子郵件,其中包含了一個(gè)鏈接,該鏈接指向 PasswordControllergetReset 方法,你需要為該電子郵件創(chuàng)建一個(gè)視圖 resources/views/emails/password.blade.php。該視圖將會(huì)獲取包含密碼重置令牌的$token 變量,用于和用戶重置密碼請求進(jìn)行匹配。下面是一個(gè)電子郵件視圖的例子:

<!-- resources/views/emails/password.blade.php -->
Click here to reset your password: {{ url('password/reset/'.$token) }}

5.3.2 密碼重置表單示例

當(dāng)用戶點(diǎn)擊電子郵件中的鏈接來重置密碼時(shí),需要提交一個(gè)密碼重置表單,該視圖位于 resources/views/auth/reset.blade.php。 下面是一個(gè)密碼重置表單示例:

<!-- resources/views/auth/reset.blade.php -->

<form method="POST" action="/password/reset">
    {!! csrf_field() !!}
    <input type="hidden" name="token" value="{{ $token }}">

    <div>
        <input type="email" name="email" value="{{ old('email') }}">
    </div>

    <div>
        <input type="password" name="password">
    </div>

    <div>
        <input type="password" name="password_confirmation">
    </div>

    <div>
        <button type="submit">
            Reset Password
        </button>
    </div>
</form>

5.4 重置密碼后

如果你已經(jīng)定義好路由和視圖來重置用戶密碼,只需要在瀏覽器中訪問這些路由即可??蚣茏詭У?PasswordController 已經(jīng)包含了發(fā)送密碼重置鏈接郵件以及更新數(shù)據(jù)庫中密碼的邏輯。 密碼被重置后,用戶將會(huì)自動(dòng)登錄到應(yīng)用并重定向到/home。你可以通過定義上 PasswordControllerredirectTo 屬性來自定義 post 密碼重置跳轉(zhuǎn)鏈接:

protected $redirectTo = '/dashboard';

注意:默認(rèn)情況下,密碼重置令牌一小時(shí)內(nèi)有效,你可以通過修改 config/auth.php 文件中的選項(xiàng) reminder.expire 來改變有效時(shí)間。

6、社會(huì)化登錄認(rèn)證

Laravel 中還可以使用Laravel Socialite通過 OAuth 提供者進(jìn)行簡單、方便的認(rèn)證,也就是社會(huì)化登錄,目前支持使用 Facebook、Twitter、LinkedIn、Google 和 Bitbucket 進(jìn)行登錄認(rèn)證。

要使用社會(huì)化登錄,需要在 composer.json 文件中添加依賴:

composer require laravel/socialite

6.1 配置

安裝完社會(huì)化登錄庫后,在配置文件 config/app.php 中注冊 Laravel\Socialite\SocialiteServiceProvider

'providers' => [
    // 其它服務(wù)提供者...
    Laravel\Socialite\SocialiteServiceProvider::class,
],

還要在 app 配置文件中添加 Socialite 門面到 aliases 數(shù)組:

'Socialite' => Laravel\Socialite\Facades\Socialite::class,

你還需要為應(yīng)用使用的 OAuth 服務(wù)添加認(rèn)證信息,這些認(rèn)證信息位于配置文件 config/services.php,而且鍵為 facebook, twitter,linkedin, google, githubbitbucket,這取決于應(yīng)用需要的提供者。例如:

'github' => [
    'client_id' => 'your-github-app-id',
    'client_secret' => 'your-github-app-secret',
    'redirect' => 'http://your-callback-url',
],

6.2 基本使用

接下來,準(zhǔn)備好認(rèn)證用戶!你需要兩個(gè)路由:一個(gè)用于重定向用戶到 OAuth 提供者,另一個(gè)用戶獲取認(rèn)證后來自提供者的回調(diào)。我們使用 Socialite 門面訪問 Socialite

<?php

namespace App\Http\Controllers;

use Socialite;
use Illuminate\Routing\Controller;

class AuthController extends Controller{
    /**
     * 將用戶重定向到 GitHub 認(rèn)證頁面.
     *
     * @return Response
     */
    public function redirectToProvider()
    {
        return Socialite::driver('github')->redirect();
    }

    /**
     * 從 GitHub 獲取用戶信息.
     *
     * @return Response
     */
    public function handleProviderCallback()
    {
        $user = Socialite::driver('github')->user();

        // $user->token;
    }
}

redirect 方法將用戶發(fā)送到 OAuth 提供者,user 方法讀取請求信息并從提供者中獲取用戶信息,在重定向用戶之前,你還可以在請求上使用 scope 方法設(shè)置”作用域”,該方法將會(huì)重寫已存在的所有作用域:

return Socialite::driver('github')
            ->scopes(['scope1', 'scope2'])->redirect();

當(dāng)然,你需要定義路由到控制器方法:

 Route::get('auth/github', 'Auth\AuthController@redirectToProvider');
 Route::get('auth/github/callback', 'Auth\AuthController@handleProviderCallback');

6.2.1 獲取用戶信息

有了用戶實(shí)例之后,可以獲取用戶的更多詳情:

$user = Socialite::driver('github')->user();
// OAuth Two Providers
$token = $user->token;
// OAuth One Providers
$token = $user->token;
$tokenSecret = $user->tokenSecret;
// All Providers
$user->getId();
$user->getNickname();
$user->getName();
$user->getEmail();
$user->getAvatar();

7、添加自定義認(rèn)證驅(qū)動(dòng)

如果你沒有使用傳統(tǒng)的關(guān)系型數(shù)據(jù)庫存儲(chǔ)用戶信息,你需要使用自己的認(rèn)證驅(qū)動(dòng)擴(kuò)展 Laravel。我們使用 Auth門面上的 extend 方法來定義自定義的驅(qū)動(dòng),你需要在服務(wù)提供者調(diào)用 extend 方法:

<?php

namespace App\Providers;

use Auth;
use App\Extensions\RiakUserProvider;
use Illuminate\Support\ServiceProvider;

class AuthServiceProvider extends ServiceProvider{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Auth::extend('riak', function($app) {
            // 返回 Illuminate\Contracts\Auth\UserProvider 實(shí)例...
            return new RiakUserProvider($app['riak.connection']);
        });
    }

    /**
     * 在容器中注冊綁定.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

通過 extend 方法注冊驅(qū)動(dòng)后,你可以在配置文件 config/auth.php 中切換到新的驅(qū)動(dòng)。

7.1 UserProvider 契約

Illuminate\Contracts\Auth\UserProvider 實(shí)現(xiàn)只負(fù)責(zé)從持久化存儲(chǔ)系統(tǒng)中獲取 Illuminate\Contracts\Auth\Authenticatable 實(shí)現(xiàn),例如 MySQL、Riak 等等。這兩個(gè)接口允許 Laravel 認(rèn)證機(jī)制繼續(xù)起作用而不管用戶數(shù)據(jù)如何存儲(chǔ)或者何種類來展現(xiàn)。 讓我們先看看 Illuminate\Contracts\Auth\UserProvider契約:

<?php

namespace Illuminate\Contracts\Auth;

interface UserProvider {

    public function retrieveById($identifier);
    public function retrieveByToken($identifier, $token);
    public function updateRememberToken(Authenticatable $user, $token);
    public function retrieveByCredentials(array $credentials);
    public function validateCredentials(Authenticatable $user, array $credentials);

}

retrieveById 方法通常獲取一個(gè)代表用戶的鍵,例如 MySQL 數(shù)據(jù)中的自增 ID。該方法獲取并返回匹配該 ID 的 Authenticatabl 實(shí)現(xiàn)。 retrieveByToken 函數(shù)通過唯一標(biāo)識(shí)和存儲(chǔ)在 remember_token 字段中的“記住我”令牌獲取用戶。和上一個(gè)方法一樣,該方法也返回 Authenticatabl 實(shí)現(xiàn)。

updateRememberToken 方法使用新的$token 更新$userremember_token 字段,新令牌可以是新生成的令牌(在登錄是選擇“記住我”被成功賦值)或者 null(用戶退出)。

retrieveByCredentials 方法在嘗試登錄系統(tǒng)時(shí)獲取傳遞給 Auth::attempt 方法的認(rèn)證信息數(shù)組。該方法接下來去底層持久化存儲(chǔ)系統(tǒng)查詢與認(rèn)證信息匹配的用戶,通常,該方法運(yùn)行一個(gè)帶“where”條件($credentials[‘username’])的查詢。然后該方法返回 UserInterface 的實(shí)現(xiàn)。這個(gè)方法不做任何密碼校驗(yàn)和認(rèn)證。

validateCredentials 方法比較給定$user$credentials 來認(rèn)證用戶。例如,這個(gè)方法比較$user->getAuthPassword()字符串和經(jīng) Hash::make 處理的$credentials['password']。這個(gè)方法只驗(yàn)證用戶認(rèn)證信息并返回布爾值。

7.2 Authenticatable 契約

既然我們已經(jīng)探索了 UserProvider 上的每一個(gè)方法,接下來讓我們看看 Authenticatable。該提供者應(yīng)該從 retrieveByIdretrieveByCredentials 方法中返回接口實(shí)現(xiàn):

<?php

namespace Illuminate\Contracts\Auth;

interface Authenticatable {

    public function getAuthIdentifier();
    public function getAuthPassword();
    public function getRememberToken();
    public function setRememberToken($value);
    public function getRememberTokenName();

}

這個(gè)接口很簡單,getAuthIdentifier 方法返回用戶“主鍵”,在 MySQL 后臺(tái)中是 ID,getAuthPassword 返回經(jīng)哈希處理的用戶密碼,這個(gè)接口允許認(rèn)證系統(tǒng)處理任何用戶類,不管是你使用的是 ORM 還是存儲(chǔ)抽象層。默認(rèn)情況下,Laravel 自帶的 app 目錄下的 User 類實(shí)現(xiàn)了這個(gè)接口,所以你可以將這個(gè)類作為實(shí)現(xiàn)例子。

上一篇:幫助函數(shù)下一篇:序列化