Laravel認(rèn)證原理以及完全自定義認(rèn)證詳解
前言
Laravel 默認(rèn)的 auth 功能已經(jīng)是很全面了,但是我們也經(jīng)常會(huì)碰到一些需要自定義的一些情況,比如驗(yàn)證的字段和默認(rèn)的不匹配,比如需要能夠同時(shí)滿足 user name 和 email 認(rèn)證等等。如何創(chuàng)建一個(gè)完全自定義的認(rèn)證呢?相比一個(gè)教程,我更傾向于介紹一下工作原理,這樣在自己修改或自定義的過(guò)程中更得心應(yīng)手。
Authenticatable 接口
Illuminate\Contracts\Auth\Authenticatable
Authenticatable 定義了一個(gè)可以被用來(lái)認(rèn)證的模型或類需要實(shí)現(xiàn)的接口,也就是說(shuō),如果需要用一個(gè)自定義的類來(lái)做認(rèn)證,需要實(shí)現(xiàn)這個(gè)接口定義的方法。
// 獲取唯一標(biāo)識(shí)的,可以用來(lái)認(rèn)證的字段名,比如 id,uuid public function getAuthIdentifierName(); // 獲取該標(biāo)示符對(duì)應(yīng)的值 public function getAuthIdentifier(); // 獲取認(rèn)證的密碼 public function getAuthPassword(); // 獲取remember token public function getRememberToken(); // 設(shè)置 remember token public function setRememberToken($value); // 獲取 remember token 對(duì)應(yīng)的字段名,比如默認(rèn)的 'remember_token' public function getRememberTokenName();
比如你的認(rèn)證模型需要用 'token' 而不是 'password' 來(lái)作為密碼驗(yàn)證,這個(gè)時(shí)候就可以修改 getAuthPassword() 方法的返回值為 'token';
Authenticatable trait
Illuminate\Auth\Authenticatable
Laravel 中定義的 Authenticatable trait,也是 Laravel auth 默認(rèn)的 User 模型使用的 trait,這個(gè) trait 定義了 User 模型默認(rèn)認(rèn)證標(biāo)示符為 'id',密碼字段為 'password',remember token 對(duì)應(yīng)的字段為 remember_token 等等。
通過(guò)重寫 User 模型的這些方法可以修改一些設(shè)置。
Guard 接口
Illuminate\Contracts\Auth\Guard
Guard 接口定義了某個(gè)實(shí)現(xiàn)了 Authenticatable (可認(rèn)證的) 模型或類的認(rèn)證方法以及一些常用的接口。
// 判斷當(dāng)前用戶是否登錄 public function check(); // 判斷當(dāng)前用戶是否是游客(未登錄) public function guest(); // 獲取當(dāng)前認(rèn)證的用戶 public function user(); // 獲取當(dāng)前認(rèn)證用戶的 id,嚴(yán)格來(lái)說(shuō)不一定是 id,應(yīng)該是上個(gè)模型中定義的唯一的字段名 public function id(); // 根據(jù)提供的消息認(rèn)證用戶 public function validate(array $credentials = []); // 設(shè)置當(dāng)前用戶 public function setUser(Authenticatable $user);
StatefulGuard 接口
Illuminate\Contracts\Auth\StatefulGuard
StatefulGuard 接口繼承自 Guard 接口,除了 Guard 里面定義的一些基本接口外,還增加了更進(jìn)一步、有狀態(tài)的 Guard.
新添加的接口有這些:
// 嘗試根據(jù)提供的憑證驗(yàn)證用戶是否合法 public function attempt(array $credentials = [], $remember = false); // 一次性登錄,不記錄session or cookie public function once(array $credentials = []); // 登錄用戶,通常在驗(yàn)證成功后記錄 session 和 cookie public function login(Authenticatable $user, $remember = false); // 使用用戶 id 登錄 public function loginUsingId($id, $remember = false); // 使用用戶 ID 登錄,但是不記錄 session 和 cookie public function onceUsingId($id); // 通過(guò) cookie 中的 remember token 自動(dòng)登錄 public function viaRemember(); // 登出 public function logout();
Laravel 中默認(rèn)提供了 3 中 guard:RequestGuard,TokenGuard,SessionGuard.
RequestGuard
Illuminate\Auth\RequestGuard
RequestGuard 是一個(gè)非常簡(jiǎn)單的 guard. RequestGuard 是通過(guò)傳入一個(gè)閉包來(lái)認(rèn)證的??梢酝ㄟ^(guò)調(diào)用 Auth::viaRequest 添加一個(gè)自定義的 RequestGuard.
SessionGuard
Illuminate\Auth\SessionGuard
SessionGuard 是 Laravel web 認(rèn)證默認(rèn)的 guard.
TokenGuard
Illuminate\Auth\TokenGuard
TokenGuard 適用于無(wú)狀態(tài) api 認(rèn)證,通過(guò) token 認(rèn)證.
UserProvider 接口
Illuminate\Contracts\Auth\UserProvider
UserProvider 接口定義了獲取認(rèn)證模型的方法,比如根據(jù) id 獲取模型,根據(jù) email 獲取模型等等.
// 通過(guò)唯一標(biāo)示符獲取認(rèn)證模型 public function retrieveById($identifier); // 通過(guò)唯一標(biāo)示符和 remember token 獲取模型 public function retrieveByToken($identifier, $token); // 通過(guò)給定的認(rèn)證模型更新 remember token public function updateRememberToken(Authenticatable $user, $token); // 通過(guò)給定的憑證獲取用戶,比如 email 或用戶名等等 public function retrieveByCredentials(array $credentials); // 認(rèn)證給定的用戶和給定的憑證是否符合 public function validateCredentials(Authenticatable $user, array $credentials);
Laravel 中默認(rèn)有兩個(gè) user provider: DatabaseUserProvider & EloquentUserProvider.
DatabaseUserProvider
Illuminate\Auth\DatabaseUserProvider
直接通過(guò)數(shù)據(jù)庫(kù)表來(lái)獲取認(rèn)證模型.
EloquentUserProvider
Illuminate\Auth\EloquentUserProvider
通過(guò) eloquent 模型來(lái)獲取認(rèn)證模型
AuthManager
Illuminate\Auth\AuthManager
Guard 用來(lái)認(rèn)證一個(gè)用戶是否認(rèn)證成功, UserProvider 用來(lái)提供認(rèn)證模型的來(lái)源,而根據(jù)項(xiàng)目的 config 管理 guard 以及自定義 guard 等等功能,則是通過(guò) AuthManager 來(lái)實(shí)現(xiàn)。
AuthManager 應(yīng)該是有點(diǎn)像策略模式里面的 Context 類以及工廠方法里面的工廠,一方面管理 Guard,另外一方面通過(guò) __call 魔術(shù)方法調(diào)用具體的策略(Guard)方法。
Auth facade 對(duì)應(yīng)的實(shí)現(xiàn)類就是 AuthManager,AuthManager 在容器中注冊(cè)為單例,用來(lái)管理所有的 guard、user provider 以及 guard 的代理工作。
自定義認(rèn)證
根據(jù)上面的知識(shí),可以知道要自定義一個(gè)認(rèn)證很簡(jiǎn)單。
- 創(chuàng)建認(rèn)證模型
創(chuàng)建一個(gè)自定義的認(rèn)證模型,實(shí)現(xiàn) Authenticatable 接口;
- 創(chuàng)建自定義的 UserProvider
創(chuàng)建一個(gè)自定義的 UserProvider,實(shí)現(xiàn) UserProvider 接口,可以返回上面自定義的認(rèn)證模型;
- 創(chuàng)建自定義的 Guard
創(chuàng)建一個(gè)自定義的 Guard,實(shí)現(xiàn) Guard或StatefulGuard 接口
- 添加 guard creator 和 user provider creator 到 AuthManager 中
在 AppServiceProvider 的 boot 方法添加如下代碼:
Auth::extend('myguard', function(){ ... return new MyGuard(); //返回自定義 guard 實(shí)例 ... }); Auth::provider('myuserprovider', function(){ return new MyUserProvider(); // 返回自定義的 user provider });
在 config\auth.php的 guards 數(shù)組中添加自定義 guard,一個(gè)自定義 guard 包括兩部分: driver 和 provider.
'oustn' => [ 'driver' => 'myguard', 'provider' => 'myusers', ],
在 config\auth.php的 providers 數(shù)組中添加自定義 user provider.
'myusers' => [ 'driver' => 'myuserprovider' // 里面具體的字段可以根據(jù)你創(chuàng)建 user provider 需要的信息自由添加,可以通過(guò) Auth::createUserProvider('myuserprovider') 創(chuàng)建 ],
設(shè)置 config\auth.php 的 defaults.guard 為 oustn.
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- Laravel6.2中用于用戶登錄的新密碼確認(rèn)流程詳解
- Laravel 5框架學(xué)習(xí)之模型、控制器、視圖基礎(chǔ)流程
- Laravel 5.4重新登錄實(shí)現(xiàn)跳轉(zhuǎn)到登錄前頁(yè)面的原理和方法
- Laravel中間件實(shí)現(xiàn)原理詳解
- Laravel模型事件的實(shí)現(xiàn)原理詳解
- 淺談Laravel隊(duì)列實(shí)現(xiàn)原理解決問(wèn)題記錄
- Laravel框架隊(duì)列原理與用法分析
- Laravel框架生命周期與原理分析
- laravel框架模型中非靜態(tài)方法也能靜態(tài)調(diào)用的原理分析
- 淺談laravel aliases別名的原理
- laravel 框架執(zhí)行流程與原理簡(jiǎn)單分析
相關(guān)文章
php+ajax實(shí)現(xiàn)無(wú)刷新動(dòng)態(tài)加載數(shù)據(jù)技術(shù)
無(wú)刷新功能我們用到很多很多的,下面我就來(lái)給各位介紹一個(gè)實(shí)例,就是實(shí)現(xiàn)php+ajax實(shí)現(xiàn)無(wú)刷新滾屏加載數(shù)據(jù),例子非常的簡(jiǎn)單大家只要按流程來(lái)操作就可以了哦。2015-04-04phpStudy配置多站點(diǎn)多域名方法及遇到的403錯(cuò)誤解決方法
這篇文章主要介紹了phpStudy配置多站點(diǎn)多域名方法及遇到的403錯(cuò)誤解決方法,需要的朋友可以參考下2017-10-10一波PHP中cURL庫(kù)的常見(jiàn)用法代碼示例
這篇文章主要介紹了一波PHP中cURL庫(kù)的常見(jiàn)用法代碼示例,類Unix世界的cURL內(nèi)置于PHP中,使Linux和Mac OS用戶倍感親切,需要的朋友可以參考下2016-05-05PHP curl實(shí)現(xiàn)抓取302跳轉(zhuǎn)后頁(yè)面的示例
這篇文章主要介紹了PHP curl實(shí)現(xiàn)抓取302跳轉(zhuǎn)后頁(yè)面的示例,主要是對(duì)CURLOPT_CUSTOMREQUEST參數(shù)的運(yùn)用,需要的朋友可以參考下2014-07-07PHP中Fatal error session_start()錯(cuò)誤解決步驟
這篇文章主要介紹了PHP中Fatal error session_start()錯(cuò)誤解決步驟,著重于錯(cuò)誤的排除步驟,一步一步排查下去,肯定可以解決這個(gè)錯(cuò)誤,需要的朋友可以參考下2014-08-08CodeIgniter記錄錯(cuò)誤日志的方法全面總結(jié)
這篇文章主要介紹了CodeIgniter記錄錯(cuò)誤日志的方法,詳細(xì)分析了CodeIgniter框架的文件結(jié)構(gòu)與相應(yīng)的功能,結(jié)合實(shí)例分析了CodeIgniter框架記錄錯(cuò)誤日志的實(shí)現(xiàn)技巧,并分析了隱藏index文件與數(shù)據(jù)傳輸?shù)燃记?總結(jié)非常全面,需要的朋友可以參考下2016-05-05