摘要:本文來源于本人博客認證解析以及改用加密驗證的默認登陸傳入郵件和用戶密碼到方法來認證,通過的值獲取,如果用戶被找到,經(jīng)哈希運算后存儲在數(shù)據(jù)中的將會和傳遞過來的經(jīng)哈希運算處理的值進行比較。
本文來源于本人博客: Laravel 5.2 Auth 認證解析以及改用 salt+passwrod 加密驗證
Larval 5.2的默認Auth登陸傳入郵件和用戶密碼到attempt 方法來認證,通過email 的值獲取,如果用戶被找到,經(jīng)哈希運算后存儲在數(shù)據(jù)中的password將會和傳遞過來的經(jīng)哈希運算處理的passwrod值進行比較。如果兩個經(jīng)哈希運算的密碼相匹配那么將會為這個用戶開啟一個認證Session。
但是往往我們一些系統(tǒng)中的密碼是通過salt+password的方式來做密碼認證的,或者一些老的系統(tǒng)是通過salt+passwrod來認證的,現(xiàn)在重構(gòu)遷移到Laravel框架中,那么密碼認證如何不用默認的passwrod的方式而用salt+password的方式認證?
要解決問題,我們最好還是先要弄明白根源,順藤摸瓜
首先看一下Laravel默認如何做密碼驗證的,看看 Auth::guard($this->getGuard())->attempt($credentials)方法做了什么:
Illuminate/Contracts/Auth/StatefulGuard.php
namespace IlluminateContractsAuth; interface StatefulGuard extends Guard { /** * Attempt to authenticate a user using the given credentials. * * @param array $credentials * @param bool $remember * @param bool $login * @return bool */ public function attempt(array $credentials = [], $remember = false, $login = true); ......
上面代碼看到attempt 是StatefulGuard 接口中的方法,第一個參數(shù)為需要認證的字段,第二個參數(shù)為是否記住登陸,第三個參數(shù)是否登陸,繼續(xù)往下看attempt 在SessionGuard中是如何實現(xiàn)的
illuminate/auth/SessionGuard.php
class SessionGuard implements StatefulGuard, SupportsBasicAuth { use GuardHelpers; ...... /** * Attempt to authenticate a user using the given credentials. * * @param array $credentials * @param bool $remember * @param bool $login * @return bool */ 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; } 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); } ....... }
看到通過$this->provider->retrieveByCredentials($credentials);和$this->provider->validateCredentials($user, $credentials);來實現(xiàn)驗證,retrieveByCredentials是用來驗證傳遞的字段查找用戶記錄是否存在,validateCredentials才是通過用戶記錄中密碼和傳入的密碼做驗證的實際過程。
這里需要注意的是$this->provider,這個provider其實是實現(xiàn)了一個IlluminateContractsAuthUserProvider 的Provider,我們看到Illuminate/Contracts/Auth下面有兩個UserProvider的實現(xiàn),分別為DatabaseUserProvider.php和EloquentUserProvider.php。但是我們驗證密碼的時候是通過哪個來驗證的是在怎么決定的?
config/auth.php
"providers" => [ "users" => [ "driver" => "eloquent", "model" => AppModelsUser::class, //這是User Model ], ],
這里我配置了 "driver" => "eloquent",那么就是通過EloquentUserProvider.php中的retrieveByCredentials來驗證的了,我們繼續(xù)看看它都干了啥
illuminate/auth/EloquentUserProvider.php
class EloquentUserProvider implements UserProvider { ...... /** * Retrieve a user by the given credentials. * * @param array $credentials * @return IlluminateContractsAuthAuthenticatable|null */ public function retrieveByCredentials(array $credentials) { // First we will add each credential element to the query as a where clause. // Then we can execute the query and, if we found a user, return it in a // Eloquent User "model" that will be utilized by the Guard instances. $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()); } ...... }
上面兩個方法 retrieveByCredentials用除了密碼以外的驗證字段查看記錄是否存在,比如用email來查找用戶記錄是否存在, 然后 validateCredentials 方法就是通過 $this->hasher->check來將輸入的密碼和哈希的密碼比較來驗證密碼是否正確,$plain 是提交過來的為加密密碼字符串,$user->getAuthPassword()是數(shù)據(jù)庫記錄存放的加密密碼字符串。
好了,看到這里就很明顯了,我們需要改成我們自己的密碼驗證不就是自己實現(xiàn)一下validateCredentials方法就可以了嗎,改變 $this->hasher->check為我們自己的密碼驗證就可以了,開始搞吧!
首先我們來實現(xiàn)$user->getAuthPassword();把數(shù)據(jù)庫中用戶表的salt和password傳遞到validateCredentials中來:
修改 AppModelsUser.php 添加如下代碼
public function getAuthPassword() { return ["password" => $this->attributes["password"], "salt" => $this->attributes["salt"]]; }
然后我們建立一個自己的UserProvider.php 的實現(xiàn),你可以放到任何地方,我放到自定義目錄中:
新建 app/Foundation/Auth/RyanEloquentUserProvider.php
getAuthPassword(); return sha1($authPassword["salt"] . sha1($authPassword["salt"] . sha1($plain))) == $authPassword["password"]; }
我這里通過$user->getAuthPassword();傳遞過來了用戶記錄的salt和password,然后將認證提交的密碼$plain和salt進行加密,如果加密結(jié)果和用戶數(shù)據(jù)庫中記錄的密碼字符串匹配那么認證就通過了, 當然加密的算法完全是自定義的。
最后我們將User Providers換成我們自己的RyanEloquentUserProvider
修改 app/Providers/AuthServiceProvider.php
public function boot(GateContract $gate) { $this->registerPolicies($gate); Auth::provider("ryan-eloquent", function ($app, $config) { return new RyanEloquentUserProvider($this->app["hash"], $config["model"]); }); }
修改 config/auth.php
"providers" => [ "users" => [ "driver" => "ryan-eloquent", "model" => AppModelsUser::class, ], ],
好了,再試試可以用過salt+passwrod的方式密碼認證了!
轉(zhuǎn)載請注明:?轉(zhuǎn)載自Ryan是菜鳥 | LNMP技術棧筆記
如果覺得本篇文章對您十分有益,何不 打賞一下
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/21523.html
摘要:擴展用戶認證系統(tǒng)上一節(jié)我們介紹了系統(tǒng)實現(xiàn)的一些細節(jié)知道了是如何應用看守器和用戶提供器來進行用戶認證的,但是針對我們自己開發(fā)的項目或多或少地我們都會需要在自帶的看守器和用戶提供器基礎之上做一些定制化來適應項目,本節(jié)我會列舉一個在做項目時遇到的 擴展用戶認證系統(tǒng) 上一節(jié)我們介紹了Laravel Auth系統(tǒng)實現(xiàn)的一些細節(jié)知道了Laravel是如何應用看守器和用戶提供器來進行用戶認證的,但是...
摘要:通過裝載看守器和用戶提供器裝載看守器和用戶提供器用到的方法比較多,用文字描述不太清楚,我們通過注解這個過程中用到的方法來看具體的實現(xiàn)細節(jié)。 用戶認證系統(tǒng)的實現(xiàn)細節(jié) 上一節(jié)我們介紹來Laravel Auth系統(tǒng)的基礎知識,說了他的核心組件都有哪些構(gòu)成,這一節(jié)我們會專注Laravel Auth系統(tǒng)的實現(xiàn)細節(jié),主要關注Auth也就是AuthManager是如何裝載認證用的看守器(Guard)...
摘要:新增了很多的新特性,包括了內(nèi)置多用戶認證表單數(shù)組輸入驗證隱式路由模型綁定中間件組的定義中間件訪問頻率限制等主要功能。相對于變化有點大,簡化了的目錄結(jié)構(gòu),并將路由分離出來。由于已將的路由單獨分離出來,因此只需在中添加路由規(guī)則。 Laravel 5.2 新增了很多的新特性,包括了內(nèi)置多用戶認證、表單數(shù)組輸入驗證、隱式路由模型綁定、中間件組的定義、中間件 throttle 訪問頻率限制等主要...
摘要:本文基于,主要介紹如何針對多站點分別進行用戶認證的改造,用意是最大限度利用自帶的認證系統(tǒng)。具體方案為清晰起見,項目按照不同站點組織成不同模塊。學院版用戶認證文檔版用戶認證文檔更詳細學院版驗證文檔版驗證文檔更詳細翁航版多用戶認證方案 原文發(fā)表于 http://www.jianshu.com/p/d6c112f27661 showImg(https://segmentfault.com/i...
摘要:默認的時間為周。大概意思就是如果用戶有一個,那么他可以帶著他的過來領取新的,直到周的時間后,他便無法繼續(xù)刷新了,需要重新登錄。指定在刷新令牌時要保留的聲明密鑰。為了使令牌無效,您必須啟用黑名單。指定用于對用戶進行身份驗證的提供程序。 showImg(https://segmentfault.com/img/remote/1460000012606251?w=1920&h=1280); ...
閱讀 2716·2021-09-24 09:47
閱讀 4366·2021-08-27 13:10
閱讀 2981·2019-08-30 15:44
閱讀 1281·2019-08-29 12:56
閱讀 2594·2019-08-28 18:07
閱讀 2614·2019-08-26 14:05
閱讀 2553·2019-08-26 13:41
閱讀 1265·2019-08-26 13:33