use Auth;
use Illuminate\Routing\Controller;class AuthController extends Controller { /** * Handle an authentication attempt. * * @return Response */ public function authenticate() { if (Auth::attempt(['email' => $email, 'password' => $password])) { return redirect()->intended('dashboard'); } }}
這個Auth門面它是怎麼驗證的呢?沒有資料庫查詢,沒有代碼具體可以看啊。。
回複內容:
use Auth;
use Illuminate\Routing\Controller;class AuthController extends Controller { /** * Handle an authentication attempt. * * @return Response */ public function authenticate() { if (Auth::attempt(['email' => $email, 'password' => $password])) { return redirect()->intended('dashboard'); } }}
這個Auth門面它是怎麼驗證的呢?沒有資料庫查詢,沒有代碼具體可以看啊。。
Auth 類是通過 class_alias 函數重新命名獲得的,原本是 Illuminate\Support\Facades\Auth。
不是很鼓勵 @granton 那種通過 laravel ide helper 的方式查看,不利於學習(當然,這是一種技巧,只是不太適合正在學習的新人,倒是適合在項目開發中快速定位源,因為我就是這麼做的)。
繼續,如果真想要理解整個架構中類似這類的問題,就是順著架構走一遍,不但學得快,還能發現一些新大陸。在這裡針對問題只提文檔中說過的部分:服務提供者、服務容器、門面模式。
Facade 指門面模式,開頭我提了那個 Auth 的源頭,是一個 Facade,查看原始碼,實際發揮作用的就一行,你如果願意去看的話,實際就是一個方法返回一個文本字串。我建議你去閱讀文檔關於 服務提供者 的部分,那個地方是構建架構功能的核心,利用服務提供者在 服務容器 註冊一個 AuthManager 的供應者,在調用 Facade 時,Facade 根據那個方法返回的字串自動解析產生出 AuthManager 執行個體(嚴格上講,AuthManager 是一個單例,通過其註冊的 Provider 可查)。AuthManager 提供了 Auth 這個 Facade 的所有功能,包括自動(根據配置)選擇驅動,由驅動提供給你這些如 attempt、login、check 這些方法。
如果你仔細閱讀完任何一個功能的文檔,尤其是 laravel 自身組件的,你都會發現他們支援擴充,擴充的方式也是利用服務容器,這是架構的核心。擴充你說的方法、改變加密方式非常簡單。
多讀文檔。
2016-07-27 補充:
只要明白這個架構的運行機制就很容易懂,實際上不複雜,大致如下(忽略不是很重要的細節,具體可以閱讀源碼):
建立 Illuminate\Foundation\Application 執行個體;
(對於 Web 應用程式)建立 Http 核心執行個體 App\Http\Kernel ---> Illuminate\Foundation\Http\Kernel,箭頭表示繼承關係;
註冊服務提供者,並執行裡面的註冊行為,認證組件(Illuminate\Auth\AuthManager)就是在Illuminate\Auth\AuthServiceProvider 中被註冊,註冊完畢執行後續操作;
後續服務啟動,如中介軟體載入、路由分發、響應處理,至此完成流程。
上述流程中提到了一個 服務提供者(Service Provider),就是 Illuminate\Auth\AuthServiceProvider,可以看到在項目配置 config/app.php 中被註冊,裡面有一段重點:
protected function registerAuthenticator(){ $this->app->singleton('auth', function ($app) { $app['auth.loaded'] = true; return new AuthManager($app); }); $this->app->singleton('auth.driver', function ($app) { return $app['auth']->guard(); });}
可以看到註冊了一個名為 auth 的單例,是一個 Illuminate\Auth\AuthManager 對象,我們所有通過 \Auth 類訪問的方法功能都由其提供,而 \Auth 類是一個由 class_alias 重新命名得到的類,實際上訪問 \Auth 就等於訪問 Illuminate\Support\Facades\Auth,Illuminate\Support\Facades\Auth 是一個 Facade 的繼承,提供了一個方法,查看原始碼:
class Auth extends Facade{ /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'auth'; }}
注意到那個 return 'auth'; 沒,這個傳回值就是 Service Provider 中註冊的那個。為何 Facade 類能夠擁有其指向的對象的方法?實際上是利用了魔術方法 __callStatic,可通過查看 Illuminate\Support\Facades\Facade 源碼得知。文檔也提到過。
至於你們去查看 AuthManager 並沒發現一些可被執行的方法,實際上是因為 AuthManager 下還有一系列驅動(Driver),這些驅動使得 Auth 組件高度可定製化,文檔上對這塊做了著重講解,驅動由兩類構成,分別是實現了 Illuminate\Contracts\Auth\UserProvider 介面和 Illuminate\Contracts\Auth\Authenticatable 介面的類的執行個體,後者是用於提供認證組件擷取認證對象資訊的介面,比如擷取賬戶、密碼的方法,前者則是你們關注的,尤其是 retrieveByCredentials 和 validateCredentials 這兩個介面方法,retrieveByCredentials 用於根據 attempt 傳入的憑據擷取使用者執行個體的,validateCredentials 適用於驗證憑據是否有效(想改變密碼驗證方式的就是通過該處實現)。
關於如何擴充、定製 Auth 組件,文檔有說明,so~~~多讀文檔,這種問題讀了文檔,自然解決。不是簡單看就完了,做到我說到任何一點你都知道在文檔哪裡去找,才說明你真的是讀了文檔的。我上面所提的所有,文檔都寫了。。。
以上。
如果使用 ide-helper, 可以在 _ide_helper.php 中看到這段代碼
class Auth extends \Illuminate\Support\Facades\Auth{ // ...}
其中
/** * Attempt to authenticate a user using the given credentials. * * @param array $credentials * @param bool $remember * @param bool $login * @return bool * @static */public static function attempt($credentials = array(), $remember = false, $login = true){ return \Illuminate\Auth\SessionGuard::attempt($credentials, $remember, $login);}
也就是說,這個 attempt 方法調用的是 \Illuminate\Auth\SessionGuard::attempt($credentials, $remember, $login) 方法。
具體的登陸驗證的邏輯在裡面。
config裡的auth.php裡配置了資料模型的吧,指定了model進行資料查詢和匹配