# 身份验证
- [介绍](#introduction)
- [Laravel Fortify](#laravel-fortify)
- [视图 / 页面](#views-pages)
- [自定义身份验证视图](#customizing-the-authentication-views)
- [自定义身份验证流程](#customizing-the-authentication-process)
- [自定义用户身份验证](#customizing-user-authentication)
- [自定义身份验证管道](#customizing-the-authentication-pipeline)
- [密码重置](#password-reset)
- [Actions](#actions)
- [视图 / 页面](#views-pages-2)
## 介绍
Laravel Jetstream 自动为你的项目提供了登录、双因素登录、注册、密码重置和电子邮件验证等功能,让你可以专注于构建你关心的功能,而不用在意用户身份验证的细节。
![Screenshot of Authentication](https://cdn.learnku.com/uploads/images/202303/10/24594/ybgNR68Npb.png!large)
## Laravel Fortify
在底层,Jetstream 的身份验证部分由 [Laravel Fortify](https://github.com/laravel/fortify) 提供支持,它是一个与前端无关的 Laravel 后端身份验证。从本质上讲,Fortify 定义了应用程序身份验证功能实现所需的路由和控制器,而 Jetstream UI 则向这些路由发出请求。
当安装 Jetstream 时,`config/fortify.php` 配置文件会被安装到你的应用程序中。在这个配置文件中,你可以自定义 Fortify 行为的各个方面,例如应该使用哪个身份验证守卫、用户在身份验证后应该重定向到哪里等等。
在 `fortify` 配置文件中,你还可以禁用 Fortify 的全部功能,比如更新个人资料或密码的功能。
## 视图 / 页面
当使用 Livewire 技术栈时,登录视图是使用 `resources/views/auth/login.blade.php` Blade模板显示的。当使用 Inertia 技术栈时,这个视图是使用 `resources/js/Pages/Auth/Login.vue` 模板显示的。包含这些视图的目录也包含了其他与身份验证相关的视图/页面。
### 自定义身份验证视图
Laravel Jetstream 会自动为你应用程序的登录和其他认证界面渲染相应的视图。但是, 有时你可能想自定义一个特定身份验证视图的渲染方式或者传递给视图的数据.
所有 Fortify 的身份验证视图渲染逻辑都可以使用 `Laravel\Fortify\Fortify` 类提供的相应方法进行自定义。通常,你应该在你应用程序的 `App\Providers\JetstreamServiceProvider` 类的 `boot` 方法中调用这个方法:
```php
use Laravel\Fortify\Fortify;
/**
* 启动任何应用程序服务。
*/
public function boot(): void
{
Fortify::loginView(function () {
return view('auth.login');
});
}
```
#### 自定义 Inertia 身份验证视图
如果你的应用程序使用的是 Inertia 技术栈,可以从你的视图自定义闭包中返回 Inertia 页面:
```php
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
use Laravel\Fortify\Fortify;
Fortify::loginView(function () {
return Inertia::render('Auth/Login', [
'canResetPassword' => Route::has('password.request'),
'status' => session('status'),
]);
});
```
## 自定义身份验证流程
### 自定义用户身份验证
有时,你可能想完全自定义用户凭证的身份验证方式和用户从应用程序数据库中的检索方式。幸运的是,Jetstream 允许你使用 `Fortify::authenticateUsing` 方法轻松地实现这一点。
`authenticateUsing` 方法接受一个闭包,该闭包接收传入的HTTP请求。闭包负责验证请求中附加的登录凭据并返回相关的用户实例。如果凭证无效或者找不到用户,闭包应该返回 `null` 或者 `false` 。通常,这个方法应该在你的 `JetstreamServiceProvider` 类的 `boot` 方法中调用:
```php
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Laravel\Fortify\Fortify;
/**
* 启动任何应用程序服务。
*/
public function boot(): void
{
// ...
Fortify::authenticateUsing(function (Request $request) {
$user = User::where('email', $request->email)->first();
if ($user &&
Hash::check($request->password, $user->password)) {
return $user;
}
});
}
```
如果你喜欢将你的自定义认证过程封装在一个类中,而不是一个闭包,你可以向`authenticateUsing`方法传递一个 PHP "callable" 数组。
```php
use App\Actions\AuthenticateLoginAttempt;
use Laravel\Fortify\Fortify;
Fortify::authenticateUsing([new AuthenticateLoginAttempt, '__invoke']);
```
### 自定义身份验证管道
Laravel Fortify,是 Jetstream 的底层身份验证库,通过一个 invokable 类的管道来验证登录请求。
如果你想,你可以定义一个自定义的管道类,将登录请求传递给这些类进行认证。每个类都应该有一个 `__invoke` 方法,它接收传入的 `Illuminate\Http\Request` 实例,并且像中间件一样,有一个 `$next` 变量,它被调用将请求传递给管道中的下一个类。
要定义你的自定义管道,你可以使用 `Fortify::authenticateThrough` 方法。这个方法接受一个闭包,它应该返回一个类的数组,以便通过管道来处理登录请求。通常,这个方法应该在你的 `App\Providers\JetstreamServiceProvider` 类的 `boot` 方法中调用。
下面的例子包含了默认的管道定义,你可以用它作为修改时的起点。
```php
use Laravel\Fortify\Actions\AttemptToAuthenticate;
use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
use Laravel\Fortify\Fortify;
use Illuminate\Http\Request;
Fortify::authenticateThrough(function (Request $request) {
return array_filter([
config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
RedirectIfTwoFactorAuthenticatable::class,
AttemptToAuthenticate::class,
PrepareAuthenticatedSession::class,
]);
});
```
## 密码重置
除了构建与登录/认证相关的视图和 actions 外,Jetstream 还提供了用户在忘记密码时重置密码所需的资源。当然, 这个功能是利用Laravel的底层[密码重置功能](https://laravel.com/docs/10.x/passwords).
> 提示:Laravel 电子邮件
> 在使用密码重置功能之前, 你应该确保你的Laravel应用程序配置好了 [发送电子邮件](https://laravel.com/docs/mail) 。否则, Laravel 将无法向应用程序的用户发送密码重置链接.
### Actions
与 Jetstream 的大多数功能一样,进行密码重置请求而执行的后端逻辑可以在你应用程序中的 action 类中找到。记住,actions 是负责执行与 Jetstream 或 Fortify 功能相关的单一任务的细粒度类。
具体来说,当用户重置密码时,将调用 `App\Actions\Fortify\ResetUserPassword` 类。这个 action 负责验证用户的新密码并更新用户实例上的密码。因此,你想对用户密码重置逻辑进行的任何自定义都应该在这个类中进行。这个 action 接收一个`$input`数组,它包含了所有传入的请求输入。
#### 密码验证规则
`AppActions\Fortify\CreateNewUser`、`AppActions\Fortify\ResetUserPassword`和`AppActions\Fortify\UpdateUserPassword` actions 都使用`AppActions\Fortify\PasswordValidationRules` trait 。
你可能已经注意到了,`App\Actions\Fortify\PasswordValidationRules` trait 利用了一个自定义的`Laravel\Fortify\Rules\Password`验证规则对象。这个对象允许轻松地自定义你的应用程序的密码要求。默认情况下,该规则要求密码长度至少为8个字符。但是,你可以使用以下方法来自定义密码的要求:
```php
use Laravel\Fortify\Rules\Password;
// 要求至少有10个字符...
(new Password)->length(10)
// 要求至少有一个大写字母...
(new Password)->requireUppercase()
// 要求至少有一个数字字符...
(new Password)->requireNumeric()
// 要求至少有一个特殊字符...
(new Password)->requireSpecialCharacter()
```
当然,这些方法可以链式调用,以定义你的应用程序的密码验证规则:
```php
(new Password)->length(10)->requireSpecialCharacter()
```
### 视图 / 页面
Jetstream 的密码重置功能使用两个界面实现:一个界面用于用户请求密码重置链接,另一个界面让用户重置密码。
#### 密码重置链接请求
当使用 Livewire 技术栈时,密码重置链接请求视图使用 `resources/views/auth/forgot-password.blade.php` Blade模板显示。当使用 Inertia 技术栈时,该视图使用 `resources/js/Pages/Auth/ForgotPassword.vue` 模板显示。
#### 重置密码
当使用 Livewire 技术栈时,密码重置视图使用 `resources/views/auth/reset-password.blade.php` Blade模板显示。当使用 Inertia 技术栈时,该视图使用 `resources/js/Pages/Auth/ResetPassword.vue` 模板显示。