Open xiaohuilam opened 6 years ago
Laravel 提供了完善的用户状态判断鉴定、验证机制,这篇文章我们用十五分钟左右的时间来深入框架内部来了解它。 在学习之前,建议先查阅 Laravel China 文档库 > Laravel 5.7 > 用户认证,熟悉用法后,学习效率更高。
Illuminate\Auth\SessionGuard
guard
web
Illuminate\Auth\EloquentUserProvider
App\Http\Middleware\Authenticate
App\User
User
Illuminate\Auth\Authenticatable
Illuminate\Foundation\Auth\User
Auth::guard 可用的守护者定义在: https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L38-L48
这些配置文件中的 providers 定义在 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L67-L77
providers
而 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L40 和 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L45
session 和 token 分别指的是 Illuminate\Auth\SessionGuard 和 Illuminate\Auth\TokenGuard。
session
token
Illuminate\Auth\TokenGuard
具体的构建方法见 AuthManager::createSessionDriver 和 AuthManager::createTokenDriver,这两个方法是在 AuthManager::resolve 时用以下代码调用的。https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L91
AuthManager::createSessionDriver
AuthManager::createTokenDriver
AuthManager::resolve
Illuminate\Auth\AuthManager 类 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L8-L12 用到了 Illuminate\Auth\CreatesUserProviders trait 此 trait 提供如下方法
Illuminate\Auth\AuthManager
Illuminate\Auth\CreatesUserProviders
在 Illuminate\Foundation\Application 的 registerCoreContainerAliases 方法中,注册 auth 时, Illuminate\Auth\AuthManager 被使用。 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Foundation/Application.php#L1074-L1117 容器对象的 registerCoreContainerAliases 方法是在 __construct 阶段被触发的。
Illuminate\Foundation\Application
registerCoreContainerAliases
auth
__construct
在 Illuminate\Auth\AuthServiceProvider 中的 register 方法, https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthServiceProvider.php#L17-L26
Illuminate\Auth\AuthServiceProvider
register
registerAuthenticator 方法为 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthServiceProvider.php#L33-L47
registerAuthenticator
registerUserResolver 方法为 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthServiceProvider.php#L54-L61
registerUserResolver
这里便将 auth 和 Illuminate\Contracts\Auth\Authenticatable 成功的从 Application 中的 alias 升级为 singleton 。
Illuminate\Contracts\Auth\Authenticatable
Application
在我们的 config/app.php 的 providers 第一个便是 Illuminate\Auth\AuthServiceProvider https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/app.php#L122-L127
config/app.php
到这里,web 环境框架启动部分所有初始化用户状态维护机制就完成。
当一个路由声明必须登陆后可访问,也就是 auth 中间件,会触发: https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php#L24-L27 触发容器构建 AuthManager
AuthManager
在容器构建 AuthManager 时,会触发 __construct https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L49-L56
中间件的 handle https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php#L39-L44
handle
调用了中间件 authenticate 方法 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php#L55-L70
authenticate
如果没登陆,报错 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php#L67-L69
如果手工在业务中使用 auth()->user() 会触发 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L290-L293
auth()->user()
AuthManager 的 guard() 默认返回的是 SessionGuard,所以 auth()->user() 调用的是 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php#L113-L151
guard()
SessionGuard
其 131 行的 $this->provider->retrieveById($id) 调用了 EloquentUserProvider::retrieveById https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php#L46-L53
$this->provider->retrieveById($id)
EloquentUserProvider::retrieveById
$this->createModel() 返回的是 $this->model,是在 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php#L34-L38 设置进去的。
$this->createModel()
$this->model
在 AuthManager 调用 createUserProvider 后调用 createEloquentProvider 方法时, https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php#L24-L45 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php#L80-L83
createUserProvider
createEloquentProvider
其传进去的 $config 的获取逻辑为 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php#L54-L59
$config
也就是这里设定的 'model' => App\User::class 了 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L67-L77
'model' => App\User::class
前面 getAuthIdentifierName 的方法,就是调用 App\User::getAuthIdentifierName 来查找用户了。 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php#L50-L52
getAuthIdentifierName
App\User::getAuthIdentifierName
本文章采用「署名 4.0 国际」创作共享协议, 转载前请阅读 相关说明 »
相关类
Illuminate\Auth\SessionGuard
guard
定义为web
生效Illuminate\Auth\EloquentUserProvider
App\Http\Middleware\Authenticate
App\User
User
模型Illuminate\Auth\Authenticatable
App\User
的父类Illuminate\Foundation\Auth\User
所使用配置文件解析
Auth::guard 可用的守护者定义在: https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L38-L48
这些配置文件中的
providers
定义在 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L67-L77而 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L40 和 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L45
session
和token
分别指的是Illuminate\Auth\SessionGuard
和Illuminate\Auth\TokenGuard
。注册流程 基础 + 容器部分
Illuminate\Auth\AuthManager
类 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L8-L12 用到了Illuminate\Auth\CreatesUserProviders
trait 此 trait 提供如下方法在
Illuminate\Foundation\Application
的registerCoreContainerAliases
方法中,注册auth
时,Illuminate\Auth\AuthManager
被使用。 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Foundation/Application.php#L1074-L1117 容器对象的registerCoreContainerAliases
方法是在__construct
阶段被触发的。注册流程 服务提供者 Illuminate\Auth\AuthServiceProvider
在
Illuminate\Auth\AuthServiceProvider
中的register
方法, https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthServiceProvider.php#L17-L26registerAuthenticator
方法为 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthServiceProvider.php#L33-L47registerUserResolver
方法为 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthServiceProvider.php#L54-L61这里便将
auth
和Illuminate\Contracts\Auth\Authenticatable
成功的从Application
中的 alias 升级为 singleton 。在我们的
config/app.php
的providers
第一个便是Illuminate\Auth\AuthServiceProvider
https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/app.php#L122-L127到这里,web 环境框架启动部分所有初始化用户状态维护机制就完成。
中间件流程 限制登陆后可访问
当一个路由声明必须登陆后可访问,也就是
auth
中间件,会触发: https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php#L24-L27 触发容器构建AuthManager
在容器构建
AuthManager
时,会触发__construct
https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L49-L56中间件的
handle
https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php#L39-L44调用了中间件
authenticate
方法 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php#L55-L70如果没登陆,报错 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php#L67-L69
获取当前用户流程
如果手工在业务中使用
auth()->user()
会触发 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L290-L293AuthManager
的guard()
默认返回的是SessionGuard
,所以auth()->user()
调用的是 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php#L113-L151其 131 行的
$this->provider->retrieveById($id)
调用了EloquentUserProvider::retrieveById
https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php#L46-L53$this->createModel()
返回的是$this->model
,是在 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php#L34-L38 设置进去的。在
AuthManager
调用createUserProvider
后调用createEloquentProvider
方法时, https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php#L24-L45 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php#L80-L83其传进去的
$config
的获取逻辑为 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/CreatesUserProviders.php#L54-L59也就是这里设定的
'model' => App\User::class
了 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L67-L77前面
getAuthIdentifierName
的方法,就是调用App\User::getAuthIdentifierName
来查找用户了。 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php#L50-L52