xiaohuilam / laravel

Laravel 深入详解 —— 源代码解析,新手进阶指南
433 stars 80 forks source link

16. UserProvider、Guard 和 Authenticatable 机制 #17

Open xiaohuilam opened 6 years ago

xiaohuilam commented 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 这是一个 trait,被 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#L40https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/config/auth.php#L45

sessiontoken 分别指的是 Illuminate\Auth\SessionGuardIlluminate\Auth\TokenGuard

具体的构建方法见 AuthManager::createSessionDriverAuthManager::createTokenDriver,这两个方法是在 AuthManager::resolve 时用以下代码调用的。https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L91

注册流程 基础 + 容器部分

Illuminate\Auth\AuthManagerhttps://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php#L8-L12 用到了 Illuminate\Auth\CreatesUserProviders trait 此 trait 提供如下方法

Illuminate\Foundation\ApplicationregisterCoreContainerAliases 方法中,注册 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-L26

registerAuthenticator 方法为 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthServiceProvider.php#L33-L47

registerUserResolver 方法为 https://github.com/xiaohuilam/laravel/blob/4d76a687b67902666a8ff308952ffddfeea8e44e/vendor/laravel/framework/src/Illuminate/Auth/AuthServiceProvider.php#L54-L61

这里便将 authIlluminate\Contracts\Auth\Authenticatable 成功的从 Application 中的 alias 升级为 singleton 。

在我们的 config/app.phpproviders 第一个便是 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-L293

AuthManagerguard() 默认返回的是 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::classhttps://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


本文章采用「署名 4.0 国际」创作共享协议, 转载前请阅读 相关说明 »