Fortify

简介

Laravel Fortify 是 Laravel 的前端无关认证后端实现。Fortify 注册了实现 Laravel 所有认证功能所需的路由和控制器,包括登录、注册、密码重置、邮箱验证等。安装 Fortify 后,你可以运行 route:list Artisan 命令查看 Fortify 注册的路由。

由于 Fortify 不提供自己的用户界面,它旨在与你自己的用户界面配合使用,由你的界面向其注册的路由发起请求。我们将在本文档的其余部分讨论如何向这些路由发起请求。

信息

请记住,Fortify 是一个旨在帮助你快速实现 Laravel 认证功能的包。你并非必须使用它。 你始终可以按照认证、密码重置和邮箱验证文档中的说明手动与 Laravel 的认证服务交互。

什么是 Fortify?

如前所述,Laravel Fortify 是 Laravel 的前端无关认证后端实现。Fortify 注册了实现 Laravel 所有认证功能所需的路由和控制器,包括登录、注册、密码重置、邮箱验证等。

你并非必须使用 Fortify 才能使用 Laravel 的认证功能。 你始终可以按照认证、密码重置和邮箱验证文档中的说明手动与 Laravel 的认证服务交互。

如果你是 Laravel 新手,你可能希望了解我们的应用起步套件。Laravel 的应用起步套件在内部使用 Fortify 为你的应用提供包含使用 Tailwind CSS 构建的用户界面的认证脚手架。这使你能够学习和熟悉 Laravel 的认证功能。

Laravel Fortify 本质上是将我们应用起步套件的路由和控制器提取出来,作为一个不包含用户界面的包提供。这使你仍然可以快速搭建应用认证层的后端实现,而不被任何特定的前端观点所束缚。

何时应该使用 Fortify?

你可能想知道何时适合使用 Laravel Fortify。首先,如果你正在使用 Laravel 的应用起步套件,则无需安装 Laravel Fortify,因为所有 Laravel 应用起步套件都使用 Fortify 并已提供完整的认证实现。

如果你没有使用应用起步套件且你的应用需要认证功能,你有两个选择:手动实现应用的认证功能,或使用 Laravel Fortify 提供这些功能的后端实现。

如果你选择安装 Fortify,你的用户界面将向本文档中详述的 Fortify 认证路由发起请求来认证和注册用户。

如果你选择手动与 Laravel 的认证服务交互而不是使用 Fortify,你可以按照认证、密码重置和邮箱验证文档中的说明进行操作。

Laravel Fortify 和 Laravel Sanctum

一些开发者对 Laravel Sanctum 和 Laravel Fortify 之间的区别感到困惑。因为这两个包解决的是两个不同但相关的问题,Laravel Fortify 和 Laravel Sanctum 并不是互斥或竞争的包。

Laravel Sanctum 只关注管理 API 令牌和使用会话 Cookie 或令牌认证现有用户。Sanctum 不提供处理用户注册、密码重置等的任何路由。

如果你试图手动为提供 API 或作为单页应用后端的应用构建认证层,你完全可能同时使用 Laravel Fortify(用于用户注册、密码重置等)和 Laravel Sanctum(API 令牌管理、会话认证)。

安装

要开始使用,请使用 Composer 包管理器安装 Fortify:

composer require laravel/fortify

接下来,使用 fortify:install Artisan 命令发布 Fortify 的资源:

php artisan fortify:install

此命令会将 Fortify 的 Actions 发布到你的 app/Actions 目录(如果不存在则会创建)。此外,FortifyServiceProvider、配置文件和所有必要的数据库迁移都会被发布。

接下来,你应该迁移数据库:

php artisan migrate

Fortify 功能

fortify 配置文件包含一个 features 配置数组。此数组定义了 Fortify 默认暴露哪些后端路由/功能。我们建议你只启用以下功能,这些是大多数 Laravel 应用提供的基本认证功能:

'features' => [
    Features::registration(),
    Features::resetPasswords(),
    Features::emailVerification(),
],

禁用视图

默认情况下,Fortify 定义了用于返回视图的路由,例如登录页面或注册页面。但是,如果你正在构建 JavaScript 驱动的单页应用,你可能不需要这些路由。因此,你可以通过将应用 config/fortify.php 配置文件中的 views 配置值设置为 false 来完全禁用这些路由:

'views' => false,

禁用视图与密码重置

如果你选择禁用 Fortify 的视图并且将为应用实现密码重置功能,你仍然应该定义一个名为 password.reset 的路由,负责显示应用的"重置密码"视图。这是必要的,因为 Laravel 的 Illuminate\Auth\Notifications\ResetPassword 通知将通过 password.reset 命名路由生成密码重置 URL。

认证

要开始使用,我们需要指示 Fortify 如何返回我们的"登录"视图。请记住,Fortify 是一个无头认证库。如果你想要一个已经为你完成的 Laravel 认证功能的前端实现,你应该使用应用起步套件。

所有认证视图的渲染逻辑都可以使用 Laravel\Fortify\Fortify 类提供的相应方法来自定义。通常,你应该在应用的 App\Providers\FortifyServiceProvider 类的 boot 方法中调用此方法。Fortify 将负责定义返回此视图的 /login 路由:

use Laravel\Fortify\Fortify;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Fortify::loginView(function () {
        return view('auth.login');
    });

    // ...
}

你的登录模板应该包含一个向 /login 发起 POST 请求的表单。/login 端点期望一个字符串 email / username 和一个 password。邮箱/用户名字段的名称应与 config/fortify.php 配置文件中的 username 值匹配。此外,可以提供一个布尔 remember 字段来指示用户想要使用 Laravel 提供的"记住我"功能。

如果登录尝试成功,Fortify 会将你重定向到应用 fortify 配置文件中通过 home 配置选项配置的 URI。如果登录请求是 XHR 请求,将返回 200 HTTP 响应。

如果请求不成功,用户将被重定向回登录页面,验证错误可通过共享的 $errors Blade 模板变量获取。或者,在 XHR 请求的情况下,验证错误将随 422 HTTP 响应返回。

自定义用户认证

Fortify 将根据提供的凭据和为应用配置的认证守卫自动检索和认证用户。但是,你有时可能希望完全自定义登录凭据的认证方式和用户的检索方式。值得庆幸的是,Fortify 允许你使用 Fortify::authenticateUsing 方法轻松实现这一点。

此方法接受一个接收传入 HTTP 请求的闭包。该闭包负责验证附加到请求的登录凭据并返回关联的用户实例。如果凭据无效或找不到用户,闭包应返回 null 或 false。通常,此方法应从 FortifyServiceProvider 的 boot 方法中调用:

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Laravel\Fortify\Fortify;

/**
 * Bootstrap any application services.
 */
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;
        }
    });

    // ...
}

认证守卫

你可以在应用的 fortify 配置文件中自定义 Fortify 使用的认证守卫。但是,你应确保配置的守卫是 Illuminate\Contracts\Auth\StatefulGuard 的实现。如果你试图使用 Laravel Fortify 来认证 SPA,你应该使用 Laravel 默认的 web 守卫并结合 Laravel Sanctum。

自定义认证管道

Laravel Fortify 通过一系列可调用类的管道来认证登录请求。如果你愿意,你可以定义一个自定义的类管道,登录请求将通过该管道传输。每个类都应该有一个 __invoke 方法,该方法接收传入的 Illuminate\Http\Request 实例,并且像中间件一样,有一个 $next 变量被调用以将请求传递给管道中的下一个类。

要定义自定义管道,你可以使用 Fortify::authenticateThrough 方法。此方法接受一个闭包,该闭包应返回登录请求要通过的类数组。通常,此方法应从 App\Providers\FortifyServiceProvider 类的 boot 方法中调用。

以下示例包含默认的管道定义,你可以在进行自己的修改时将其作为起点:

use Laravel\Fortify\Actions\AttemptToAuthenticate;
use Laravel\Fortify\Actions\CanonicalizeUsername;
use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
use Laravel\Fortify\Features;
use Laravel\Fortify\Fortify;
use Illuminate\Http\Request;

Fortify::authenticateThrough(function (Request $request) {
    return array_filter([
            config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
            config('fortify.lowercase_usernames') ? CanonicalizeUsername::class : null,
            Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null,
            AttemptToAuthenticate::class,
            PrepareAuthenticatedSession::class,
    ]);
});

认证限流

默认情况下,Fortify 将使用 EnsureLoginIsNotThrottled 中间件来限制认证尝试。此中间件限制特定于用户名和 IP 地址组合的尝试。

某些应用可能需要不同的方法来限制认证尝试,例如仅按 IP 地址限制。因此,Fortify 允许你通过 fortify.limiters.login 配置选项指定自己的速率限制器。当然,此配置选项位于应用的 config/fortify.php 配置文件中。

信息

结合使用限流、双因素认证和外部 Web 应用防火墙(WAF)将为你的合法应用用户提供最强大的防御。

自定义重定向

如果登录尝试成功,Fortify 会将你重定向到应用 fortify 配置文件中通过 home 配置选项配置的 URI。如果登录请求是 XHR 请求,将返回 200 HTTP 响应。用户注销应用后,用户将被重定向到 / URI。

如果你需要对此行为进行高级自定义,你可以将 LoginResponse 和 LogoutResponse 契约的实现绑定到 Laravel 服务容器中。通常,这应该在应用的 App\Providers\FortifyServiceProvider 类的 register 方法中完成:

use Laravel\Fortify\Contracts\LogoutResponse;

/**
 * Register any application services.
 */
public function register(): void
{
    $this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
        public function toResponse($request)
        {
            return redirect('/');
        }
    });
}

双因素认证

当 Fortify 的双因素认证功能启用时,用户需要在认证过程中输入一个六位数字令牌。此令牌使用基于时间的一次性密码(TOTP)生成,可以从任何兼容 TOTP 的移动认证应用(如 Google Authenticator)中获取。

在开始之前,你应首先确保应用的 App\Models\User 模型使用了 Laravel\Fortify\TwoFactorAuthenticatable trait:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;

class User extends Authenticatable
{
    use Notifiable, TwoFactorAuthenticatable;
}

接下来,你应该在应用中构建一个页面,让用户可以管理其双因素认证设置。此页面应允许用户启用和禁用双因素认证,以及重新生成其双因素认证恢复码。

信息

默认情况下,fortify 配置文件的 features 数组指示 Fortify 的双因素认证设置在修改前需要密码确认。因此,你的应用应在继续之前实现 Fortify 的密码确认功能。

启用双因素认证

要开始启用双因素认证,你的应用应向 Fortify 定义的 /user/two-factor-authentication 端点发起 POST 请求。如果请求成功,用户将被重定向回上一个 URL,并且 status 会话变量将被设置为 two-factor-authentication-enabled。你可以在模板中检测此 status 会话变量以显示适当的成功消息。如果请求是 XHR 请求,将返回 200 HTTP 响应。

选择启用双因素认证后,用户仍必须通过提供有效的双因素认证码来"确认"其双因素认证配置。因此,你的"成功"消息应指示用户仍需要确认双因素认证:

@if (session('status') == 'two-factor-authentication-enabled')
    <div class="mb-4 font-medium text-sm">
        Please finish configuring two-factor authentication below.
    </div>
@endif

接下来,你应该显示双因素认证二维码供用户扫描到其认证器应用中。如果你使用 Blade 来渲染应用的前端,你可以使用用户实例上的 twoFactorQrCodeSvg 方法获取二维码 SVG:

$request->user()->twoFactorQrCodeSvg();

如果你正在构建 JavaScript 驱动的前端,你可以向 /user/two-factor-qr-code 端点发起 XHR GET 请求来获取用户的双因素认证二维码。此端点将返回一个包含 svg 键的 JSON 对象。

确认双因素认证

除了显示用户的双因素认证二维码外,你还应该提供一个文本输入框,让用户可以输入有效的认证码来"确认"其双因素认证配置。此认证码应通过向 Fortify 定义的 /user/confirmed-two-factor-authentication 端点发起 POST 请求来提供给 Laravel 应用。

如果请求成功,用户将被重定向回上一个 URL,并且 status 会话变量将被设置为 two-factor-authentication-confirmed:

@if (session('status') == 'two-factor-authentication-confirmed')
    <div class="mb-4 font-medium text-sm">
        Two-factor authentication confirmed and enabled successfully.
    </div>
@endif

如果向双因素认证确认端点的请求是通过 XHR 请求发起的,将返回 200 HTTP 响应。

显示恢复码

你还应该显示用户的双因素恢复码。这些恢复码允许用户在无法访问其移动设备时进行认证。如果你使用 Blade 来渲染应用的前端,你可以通过已认证的用户实例访问恢复码:

(array) $request->user()->recoveryCodes()

如果你正在构建 JavaScript 驱动的前端,你可以向 /user/two-factor-recovery-codes 端点发起 XHR GET 请求。此端点将返回一个包含用户恢复码的 JSON 数组。

要重新生成用户的恢复码,你的应用应向 /user/two-factor-recovery-codes 端点发起 POST 请求。

使用双因素认证进行认证

在认证过程中,Fortify 会自动将用户重定向到你应用的双因素认证挑战页面。但是,如果你的应用正在发起 XHR 登录请求,成功认证尝试后返回的 JSON 响应将包含一个具有 two_factor 布尔属性的 JSON 对象。你应该检查此值以知道是否应该重定向到应用的双因素认证挑战页面。

要开始实现双因素认证功能,我们需要指示 Fortify 如何返回我们的双因素认证挑战视图。Fortify 的所有认证视图渲染逻辑都可以使用 Laravel\Fortify\Fortify 类提供的相应方法来自定义。通常,你应该在应用的 App\Providers\FortifyServiceProvider 类的 boot 方法中调用此方法:

use Laravel\Fortify\Fortify;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Fortify::twoFactorChallengeView(function () {
        return view('auth.two-factor-challenge');
    });

    // ...
}

Fortify 将负责定义返回此视图的 /two-factor-challenge 路由。你的 two-factor-challenge 模板应该包含一个向 /two-factor-challenge 端点发起 POST 请求的表单。/two-factor-challenge 操作期望一个包含有效 TOTP 令牌的 code 字段或一个包含用户恢复码之一的 recovery_code 字段。

如果登录尝试成功,Fortify 会将用户重定向到应用 fortify 配置文件中通过 home 配置选项配置的 URI。如果登录请求是 XHR 请求,将返回 204 HTTP 响应。

如果请求不成功,用户将被重定向回双因素挑战页面,验证错误可通过共享的 $errors Blade 模板变量获取。或者,在 XHR 请求的情况下,验证错误将随 422 HTTP 响应返回。

禁用双因素认证

要禁用双因素认证,你的应用应向 /user/two-factor-authentication 端点发起 DELETE 请求。请记住,Fortify 的双因素认证端点在调用前需要密码确认。

Passkeys

Fortify 支持使用 WebAuthn 的 Passkey 认证。Passkey 允许用户使用平台认证器(如 Face ID、Touch ID、Windows Hello 或硬件安全密钥)进行无密码认证。

启用 Passkeys

要开始使用,请确保在应用的 fortify 配置文件中启用了 passkeys 功能:

use Laravel\Fortify\Features;

'features' => [
    // ...
    Features::passkeys([
        'confirmPassword' => true,
    ]),
],

confirmPassword 选项确定 Fortify 在注册或删除 Passkey 之前是否需要密码确认。

接下来,确保应用的 App\Models\User 模型实现了 Laravel\Fortify\Contracts\PasskeyUser 接口并使用了 Laravel\Fortify\PasskeyAuthenticatable trait:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\Contracts\PasskeyUser;
use Laravel\Fortify\PasskeyAuthenticatable;

class User extends Authenticatable implements PasskeyUser
{
    use Notifiable, PasskeyAuthenticatable;
}

Fortify 的 Passkeys 配置选项可以使用应用 config/fortify.php 文件中的 passkeys 配置数组来自定义:

'passkeys' => [
    'relying_party_id' => parse_url(config('app.url'), PHP_URL_HOST),
    'allowed_origins' => [config('app.url')],
    'user_handle_secret' => config('app.key'),
    'timeout' => 60000,
],

信息

Fortify 封装了 laravel/passkeys Composer 包并为你进行配置。如果你使用 Fortify 的 Passkeys 功能,你应该使用应用的 config/fortify.php 文件来配置 Passkeys。你不需要发布 laravel/passkeys 配置文件,在那里定义的任何值都会被 Fortify 覆盖。

relying_party_id 应与你应用的域名匹配。allowed_origins 数组列出了可以完成 Passkey 注册和认证的浏览器源。user_handle_secret 用于派生不透明的用户标识符,确保同一用户在不同的 Passkey 注册中被识别。timeout 选项控制 Passkey 注册和认证操作可以保持活动状态的时间。

Fortify 为其 Passkey 登录、确认和注册路由应用了专用的 Passkeys 速率限制器。如果需要,你可以使用 fortify.limiters.passkeys 配置选项和相应的 RateLimiter::for(...) 定义来自定义它。

JavaScript 客户端

如果你正在构建自定义前端,包括带有浏览器端脚本的 Blade 应用,你可以使用官方的 @laravel/passkeys 包。此包处理浏览器 WebAuthn 仪式并向 Fortify 的 Passkey 端点发送请求。

通过 npm 安装该包:

npm install @laravel/passkeys

然后,你可以从前端发起 Passkey 注册和验证:

import { Passkeys } from "@laravel/passkeys";

await Passkeys.register({ name: "MacBook Pro" });
await Passkeys.verify();

如果你的应用使用自定义的 Passkey 端点 URI,你可以在每次调用时覆盖路由:

await Passkeys.verify({
    routes: {
        options: "/passkeys/confirm/options",
        submit: "/passkeys/confirm",
    },
});

await Passkeys.register({
    name: "MacBook Pro",
    routes: {
        options: "/user/passkeys/options",
        submit: "/user/passkeys",
    },
});

该包还通过 @laravel/passkeys/react、@laravel/passkeys/vue 和 @laravel/passkeys/svelte 提供 React、Vue 和 Svelte 辅助工具。

使用 Passkeys 进行认证

要使用 Passkey 认证用户,你的应用应首先向 /passkeys/login/options 端点发起 GET 请求。此端点返回 WebAuthn 挑战选项,你的前端应将其传递给 navigator.credentials.get(...)。

浏览器返回凭据后,你的应用应向 /passkeys/login 发起带有凭据负载的 POST 请求。你还可以包含一个布尔 remember 字段。

如果请求成功,Fortify 将使用配置的守卫登录用户并返回:

  • 对于标准请求,重定向响应到你的预期目的地。
  • 对于 XHR 请求,包含带有 redirect 键的 JSON 负载的 200 HTTP 响应。

使用 Passkeys 确认密码

对于已认证的会话,Fortify 提供了满足 Laravel 当前会话密码确认要求的 Passkey 确认端点。

要使用 Passkey 进行确认,你的应用应首先向 /passkeys/confirm/options 发起 GET 请求。此端点返回 WebAuthn 挑战选项,你的前端应将其传递给 navigator.credentials.get(...)。

浏览器返回凭据后,你的应用应向 /passkeys/confirm 发起带有凭据负载的 POST 请求。

如果请求成功,Fortify 将当前会话标记为密码已确认并返回:

  • 对于标准请求,重定向响应到你的预期目的地。
  • 对于 XHR 请求,包含带有 redirect 键的 JSON 负载的 200 HTTP 响应。

注册 Passkeys

要为已认证用户注册 Passkey,你的应用应首先向 /user/passkeys/options 发起 GET 请求。此端点返回 WebAuthn 创建选项,你的前端应将其传递给 navigator.credentials.create(...)。

浏览器返回凭据后,你的应用应向 /user/passkeys 发起带有 name 字段和包含由 navigator.credentials.create(...) 返回的序列化 PublicKeyCredential 对象的 credential 字段的 POST 请求。

如果请求成功,Fortify 将返回:

  • 对于标准请求,带有会话中 passkey-registered 状态的重定向返回响应。
  • 包含带有 status 键的 JSON 负载以及新注册 Passkey 的 id 和 name 的 200 HTTP 响应。

删除 Passkeys

要删除 Passkey,你的应用应向 /user/passkeys/{passkey} 发起 DELETE 请求。

如果请求成功,Fortify 将返回:

  • 对于标准请求,带有会话中 passkey-deleted 状态的重定向返回响应。
  • 对于 XHR 请求,包含带有 status 键的 JSON 负载的 200 HTTP 响应。

注册

要开始实现应用的注册功能,我们需要指示 Fortify 如何返回我们的"注册"视图。请记住,Fortify 是一个无头认证库。如果你想要一个已经为你完成的 Laravel 认证功能的前端实现,你应该使用应用起步套件。

Fortify 的所有视图渲染逻辑都可以使用 Laravel\Fortify\Fortify 类提供的相应方法来自定义。通常,你应该在应用的 App\Providers\FortifyServiceProvider 类的 boot 方法中调用此方法:

use Laravel\Fortify\Fortify;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Fortify::registerView(function () {
        return view('auth.register');
    });

    // ...
}

Fortify 将负责定义返回此视图的 /register 路由。你的 register 模板应该包含一个向 Fortify 定义的 /register 端点发起 POST 请求的表单。

/register 端点期望一个字符串 name、字符串邮箱地址/用户名、password 和 password_confirmation 字段。邮箱/用户名字段的名称应与应用 fortify 配置文件中定义的 username 配置值匹配。

如果注册尝试成功,Fortify 会将用户重定向到应用 fortify 配置文件中通过 home 配置选项配置的 URI。如果请求是 XHR 请求,将返回 201 HTTP 响应。

如果请求不成功,用户将被重定向回注册页面,验证错误可通过共享的 $errors Blade 模板变量获取。或者,在 XHR 请求的情况下,验证错误将随 422 HTTP 响应返回。

自定义注册

用户验证和创建过程可以通过修改安装 Laravel Fortify 时生成的 App\Actions\Fortify\CreateNewUser Action 来自定义。

密码重置

要开始实现应用的密码重置功能,我们需要指示 Fortify 如何返回我们的"忘记密码"视图。请记住,Fortify 是一个无头认证库。如果你想要一个已经为你完成的 Laravel 认证功能的前端实现,你应该使用应用起步套件。

Fortify 的所有视图渲染逻辑都可以使用 Laravel\Fortify\Fortify 类提供的相应方法来自定义。通常,你应该在应用的 App\Providers\FortifyServiceProvider 类的 boot 方法中调用此方法:

use Laravel\Fortify\Fortify;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Fortify::requestPasswordResetLinkView(function () {
        return view('auth.forgot-password');
    });

    // ...
}

Fortify 将负责定义返回此视图的 /forgot-password 端点。你的 forgot-password 模板应该包含一个向 /forgot-password 端点发起 POST 请求的表单。

/forgot-password 端点期望一个字符串 email 字段。此字段/数据库列的名称应与应用 fortify 配置文件中的 email 配置值匹配。

如果密码重置链接请求成功,Fortify 会将用户重定向回 /forgot-password 端点,并向用户发送一封包含安全链接的邮件,用户可以使用该链接重置密码。如果请求是 XHR 请求,将返回 200 HTTP 响应。

在成功请求后被重定向回 /forgot-password 端点时,status 会话变量可用于显示密码重置链接请求尝试的状态。

$status 会话变量的值将与应用 passwords 语言文件中定义的翻译字符串之一匹配。如果你想自定义此值且尚未发布 Laravel 的语言文件,你可以通过 lang:publish Artisan 命令来完成:

@if (session('status'))
    <div class="mb-4 font-medium text-sm text-green-600">
        {{ session('status') }}
    </div>
@endif

如果请求不成功,用户将被重定向回请求密码重置链接页面,验证错误可通过共享的 $errors Blade 模板变量获取。或者,在 XHR 请求的情况下,验证错误将随 422 HTTP 响应返回。

重置密码

要完成实现应用的密码重置功能,我们需要指示 Fortify 如何返回我们的"重置密码"视图。

Fortify 的所有视图渲染逻辑都可以使用 Laravel\Fortify\Fortify 类提供的相应方法来自定义。通常,你应该在应用的 App\Providers\FortifyServiceProvider 类的 boot 方法中调用此方法:

use Laravel\Fortify\Fortify;
use Illuminate\Http\Request;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Fortify::resetPasswordView(function (Request $request) {
        return view('auth.reset-password', ['request' => $request]);
    });

    // ...
}

Fortify 将负责定义显示此视图的路由。你的 reset-password 模板应该包含一个向 /reset-password 发起 POST 请求的表单。

/reset-password 端点期望一个字符串 email 字段、一个 password 字段、一个 password_confirmation 字段和一个名为 token 的隐藏字段(包含 request()->route('token') 的值)。"email"字段/数据库列的名称应与应用 fortify 配置文件中定义的 email 配置值匹配。

处理密码重置响应

如果密码重置请求成功,Fortify 将重定向回 /login 路由,以便用户可以使用新密码登录。此外,将设置一个 status 会话变量,以便你可以在登录页面上显示重置的成功状态:

@if (session('status'))
    <div class="mb-4 font-medium text-sm text-green-600">
        {{ session('status') }}
    </div>
@endif

如果请求是 XHR 请求,将返回 200 HTTP 响应。

如果请求不成功,用户将被重定向回重置密码页面,验证错误可通过共享的 $errors Blade 模板变量获取。或者,在 XHR 请求的情况下,验证错误将随 422 HTTP 响应返回。

自定义密码重置

密码重置过程可以通过修改安装 Laravel Fortify 时生成的 App\Actions\ResetUserPassword Action 来自定义。

邮箱验证

注册后,你可能希望用户在继续访问应用之前验证其邮箱地址。要开始使用,请确保在 fortify 配置文件的 features 数组中启用了 emailVerification 功能。接下来,你应确保 App\Models\User 类实现了 Illuminate\Contracts\Auth\MustVerifyEmail 接口。

完成这两个设置步骤后,新注册的用户将收到一封提示其验证邮箱地址所有权的邮件。但是,我们需要告知 Fortify 如何显示邮箱验证页面,该页面通知用户需要点击邮件中的验证链接。

Fortify 的所有视图渲染逻辑都可以使用 Laravel\Fortify\Fortify 类提供的相应方法来自定义。通常,你应该在应用的 App\Providers\FortifyServiceProvider 类的 boot 方法中调用此方法:

use Laravel\Fortify\Fortify;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Fortify::verifyEmailView(function () {
        return view('auth.verify-email');
    });

    // ...
}

Fortify 将负责定义当用户被 Laravel 内置的 verified 中间件重定向到 /email/verify 端点时显示此视图的路由。

你的 verify-email 模板应该包含一条信息性消息,指示用户点击发送到其邮箱地址的邮箱验证链接。

如果你愿意,你可以在应用的 verify-email 模板中添加一个按钮,触发向 /email/verification-notification 端点发起 POST 请求。当此端点收到请求时,新的验证邮件链接将发送给用户,允许用户在之前的链接被意外删除或丢失时获取新的验证链接。

如果重新发送验证链接邮件的请求成功,Fortify 会将用户重定向回 /email/verify 端点并附带 status 会话变量,允许你向用户显示一条信息性消息通知他们操作已成功。如果请求是 XHR 请求,将返回 202 HTTP 响应:

@if (session('status') == 'verification-link-sent')
    <div class="mb-4 font-medium text-sm text-green-600">
        A new email verification link has been emailed to you!
    </div>
@endif

保护路由

要指定路由或路由组需要用户已验证其邮箱地址,你应该将 Laravel 内置的 verified 中间件附加到路由。verified 中间件别名由 Laravel 自动注册,作为 Illuminate\Auth\Middleware\EnsureEmailIsVerified 中间件的别名:

Route::get('/dashboard', function () {
    // ...
})->middleware(['verified']);

密码确认

在构建应用时,你偶尔会有一些操作应该要求用户在执行操作之前确认其密码。通常,这些路由由 Laravel 内置的 password.confirm 中间件保护。

要开始实现密码确认功能,我们需要指示 Fortify 如何返回应用的"密码确认"视图。请记住,Fortify 是一个无头认证库。如果你想要一个已经为你完成的 Laravel 认证功能的前端实现,你应该使用应用起步套件。

Fortify 的所有视图渲染逻辑都可以使用 Laravel\Fortify\Fortify 类提供的相应方法来自定义。通常,你应该在应用的 App\Providers\FortifyServiceProvider 类的 boot 方法中调用此方法:

use Laravel\Fortify\Fortify;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Fortify::confirmPasswordView(function () {
        return view('auth.confirm-password');
    });

    // ...
}

Fortify 将负责定义返回此视图的 /user/confirm-password 端点。你的 confirm-password 模板应该包含一个向 /user/confirm-password 端点发起 POST 请求的表单。/user/confirm-password 端点期望一个包含用户当前密码的 password 字段。

如果密码与用户的当前密码匹配,Fortify 会将用户重定向到他们试图访问的路由。如果请求是 XHR 请求,将返回 201 HTTP 响应。

如果请求不成功,用户将被重定向回密码确认页面,验证错误可通过共享的 $errors Blade 模板变量获取。或者,在 XHR 请求的情况下,验证错误将随 422 HTTP 响应返回。