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
函数重命名获得的,原本是 Illuminate\Support\Facades\Auth
。
不是很鼓励 @granton 那种通过 laravel ide helper 的方式查看,不利于学习(当然,这是一种技巧,只是不太适合正在学习的新人,倒是适合在项目开发中快速定位源,因为我就是这么做的)。
继续,如果真想要理解整个框架中类似这类的问题,就是顺着框架走一遍,不但学得快,还能发现一些新大陆。在这里针对问题只提文档中说过的部分:服务提供者、服务容器、门面模式。
Facade 指门面模式,开头我提了那个 Auth 的源头,是一个 Facade,查看源代码,实际发挥作用的就一行,你如果愿意去看的话,实际就是一个方法返回一个文本字符串。我建议你去阅读文档关于 服务提供者
的部分,那个地方是构建框架功能的核心,利用服务提供者在 服务容器
注册一个 AuthManager 的供应者,在调用 Facade 时,Facade 根据那个方法返回的字符串自动解析生成出 AuthManager 实例(严格上讲,AuthManager 是一个单例,通过其注册的 Provider 可查)。AuthManager 提供了 Auth 这个 Facade 的所有功能,包括自动(根据配置)选择驱动,由驱动提供给你这些如 attempt、login、check 这些方法。
如果你仔细阅读完任何一个功能的文档,尤其是 laravel 自身组件的,你都会发现他们支持扩展,扩展的方式也是利用服务容器,这是框架的核心。扩展你说的方法、改变加密方式非常简单。
多读文档。
只要明白这个框架的运行机制就很容易懂,实际上不复杂,大致如下(忽略不是很重要的细节,具体可以阅读源码):
创建 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
中被注册,里面有一段重点:
<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
的单例,是一个 Illuminate\Auth\AuthManager
对象,我们所有通过 \Auth
类访问的方法功能都由其提供,而 \Auth
类是一个由 class_alias
重命名得到的类,实际上访问 \Auth
就等于访问 Illuminate\Support\Facades\Auth
,Illuminate\Support\Facades\Auth
是一个 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
,可通过查看 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
中看到这段代码
<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进行数据查询和匹配