use Auth;
<code>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'); } } }</code>
這個Auth門面它是怎麼驗證的呢?沒有資料庫查詢,沒有程式碼具體可以看啊。 。
use Auth;
<code>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'); } } }</code>
這個Auth門面它是怎麼驗證的呢?沒有資料庫查詢,沒有程式碼具體可以看啊。 。
Auth 類別是透過 class_alias
函數重新命名獲得的,原本是 IlluminateSupportFacadesAuth
。
不是很鼓勵 @granton 那種透過laravel ide helper 的方式查看,不利於學習(當然,這是一種技巧,只是不太適合正在學習的新人,倒是適合在專案開發中快速定位源,因為我就是這麼做的)。
繼續,如果真想要理解整個框架中類似這類的問題,就是順著框架走一遍,不但學得快,還能發現一些新大陸。這裡針對問題只提文件中所說的部分:服務提供者、服務容器、門面模式。
Facade 指門面模式,開頭我提了那個 Auth 的源頭,是一個 Facade,查看源代碼,實際發揮作用的就一行,你如果願意去看的話,實際上就是一個方法返回一個文本字符串。我建議你去閱讀文件關於服務提供者
的部分,那個地方是構建框架功能的核心,利用服務提供者在服務容器
註冊一個AuthManager 的供應者,在調用Facade 時,Facade 根據那個方法返回的字串會自動解析產生出AuthManager 實例(嚴格上講,AuthManager 是一個單例,透過其註冊的Provider 可查)。 AuthManager 提供了 Auth 這個 Facade 的所有功能,包括自動(根據配置)選擇驅動,由驅動提供給你這些如 attempt、login、check 這些方法。
如果你仔細閱讀完任何一個功能的文檔,尤其是 laravel 自身組件的,你都會發現他們支持擴展,擴展的方式也是利用服務容器,這是框架的核心。擴展你說的方法、改變加密方式非常簡單。
多讀文檔。
只要明白這個框架的運作機制就很容易懂,實際上不複雜,大致如下(忽略不是很重要的細節,具體可以閱讀源碼):
建立 IlluminateFoundationApplication
實例;
(適用於 Web 應用)建立 Http 核心實例 AppHttpKernel
---> IlluminateFoundationHttpKernel
,箭頭表示繼承關係;
註冊服務提供者,並執行裡面的註冊行為
,認證元件(IlluminateAuthAuthManager
)就是在
後續服務啟動,如中介軟體載入、路由分發、回應處理,至此完成流程。
上述流程中提到了一個 服務提供者(Service Provider)
,就是 IlluminateAuthAuthServiceProvider
,可以看到在項目配置 config/app.php
中被註冊,裡面有一段重點:
<code>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(); }); }</code>
可以看到註冊了一個名為auth
的單例,是一個IlluminateAuthAuthManager
對象,我們所有透過Auth
類別存取的方法功能都由其提供,而Auth
重新命名得到的類,實際上訪問Auth
就等於訪問IlluminateSupportFacadesAuth
,IlluminateSupportFacadesAuth
是一個Facade 的繼承,提供了一個方法,查看源代碼:
<code>class Auth extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'auth'; } }</code>
注意到那個
return 'auth'; 沒,這個回傳值就是 Service Provider 中註冊的那個。為何 Facade 類別能夠擁有其指向的物件的方法?實際上是利用了魔術方法
__callStatic,可透過查看
IlluminateSupportFacadesFacade 原始碼得知。文檔也提到過。
至于你们去查看 AuthManager
并没发现一些可被执行的方法,实际上是因为 AuthManager
下还有一系列驱动(Driver),这些驱动使得 Auth 组件高度可定制化,文档上对这块做了着重讲解,驱动由两类构成,分别是实现了 Illuminate\Contracts\Auth\UserProvider
接口和 Illuminate\Contracts\Auth\Authenticatable
接口的类的实例,后者是用于提供认证组件获取认证对象信息的接口,比如获取账户、密码的方法,前者则是你们关注的,尤其是 retrieveByCredentials
和 validateCredentials
这两个接口方法,retrieveByCredentials
用于根据 attempt 传入的凭据获取用户实例的,validateCredentials
适用于验证凭据是否有效(想改变密码验证方式的就是通过该处实现)。
关于如何扩展、定制 Auth 组件,文档有说明,so~~~多读文档,这种问题读了文档,自然解决。不是简单看就完了,做到我说到任何一点你都知道在文档哪里去找,才说明你真的是读了文档的。我上面所提的所有,文档都写了。。。
以上。
如果使用 ide-helper, 可以在 _ide_helper.php
中看到这段代码
<code class="php">class Auth extends \Illuminate\Support\Facades\Auth{ // ... }</code>
其中
<code class="php">/** * 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); }</code>
也就是说,这个 attempt
方法调用的是 \Illuminate\Auth\SessionGuard::attempt($credentials, $remember, $login)
方法。
具体的登陆验证的逻辑在里面。
config里的auth.php里配置了数据模型的吧,指定了model进行数据查询和匹配