> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Fortify 与 Starter Kit

> 讲解与前端解耦的认证后端 Laravel Fortify 的内部设计。涵盖当前 Starter Kit 为何采用 Fortify、FortifyServiceProvider 的配置、2FA、Passkey 的启用等。

## 什么是 Fortify

[Laravel Fortify](https://github.com/laravel/fortify) 是与前端解耦的认证后端实现。它提供了登录、注册、密码重置、邮箱验证、2FA、Passkey 所需的全部路由与 Controller。

<Info>
  Fortify 本身不带 UI。通过从 Starter Kit 或自定义 UI 向 Fortify 的路由发送请求来使用其功能。
</Info>

「与前端解耦」这一设计理念很重要。无论前端使用 Blade、Inertia（React/Vue/Svelte）还是 API，都可以复用相同的认证后端。这正是 Fortify 长期被使用的原因。

## 历史：从 Jetstream 到现行 Starter Kit

```mermaid theme={null}
timeline
    title Fortify 的变迁
    2020 Laravel 8 : 与 Jetstream 同时登场
               : Fortify 作为 Jetstream 的后端被自动安装
    2020 Laravel 8 : Breeze 登场（不使用 Fortify）
               : 作为简洁的认证脚手架独立存在
    2025 Starter Kit 改版 : React/Vue Starter Kit 需要支持 2FA
                         : 于是采用 Fortify → 整个认证转向 Fortify
    2026 Passkey 支持 : Fortify 追加 Passkeys 功能
```

### 为什么当前 Starter Kit 也使用 Fortify

最初的 React/Vue Starter Kit 并未使用 Fortify。但**在需要支持二要素认证（2FA）时，直接采用 Fortify** 使整个认证转向了以 Fortify 为基础。

由于 Fortify 是按「前端无关」的思路设计，与基于 Inertia 的 Starter Kit 契合，因此持续沿用至今。

<Info>
  Fortify 是目前使用时间最长的 Laravel 官方认证包。自 2020 年问世以来，从 Jetstream 到当前 Starter Kit，形态几经变化但始终活跃。
</Info>

## 当前 Starter Kit 的构成

React/Vue Starter Kit 中，Fortify 的配置分布在以下文件：

* `app/Providers/FortifyServiceProvider.php` — 注册视图、Action、限流
* `config/fortify.php` — 启用的功能与认证配置

### `config/fortify.php` 的主要配置

```php theme={null}
use Laravel\Fortify\Features;

return [
    'guard'    => 'web',
    'username' => 'email',
    'home'     => '/dashboard',

    'limiters' => [
        'login'      => 'login',
        'two-factor' => 'two-factor',
    ],

    'features' => [
        Features::registration(),
        Features::resetPasswords(),
        Features::emailVerification(),
        Features::twoFactorAuthentication([
            'confirm'         => true,
            'confirmPassword' => true,
        ]),
    ],
];
```

Starter Kit 中 Passkey（`Features::passkeys()`）默认未启用。若要启用，将其加入 `features` 数组。

## `FortifyServiceProvider` 的设置

Starter Kit 中的 `FortifyServiceProvider` 承担 3 项职责。

### 1. 配置 Action

```php theme={null}
private function configureActions(): void
{
    Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
    Fortify::createUsersUsing(CreateNewUser::class);
}
```

用户创建与密码重置的逻辑通过 `app/Actions/Fortify/` 下的类进行自定义。验证与哈希处理都集中在此。

### 2. 配置视图

```php theme={null}
private function configureViews(): void
{
    Fortify::loginView(fn (Request $request) => Inertia::render('auth/login', [
        'canResetPassword' => Features::enabled(Features::resetPasswords()),
        'canRegister'      => Features::enabled(Features::registration()),
        'status'           => $request->session()->get('status'),
    ]));

    Fortify::resetPasswordView(fn (Request $request) => Inertia::render('auth/reset-password', [
        'email' => $request->email,
        'token' => $request->route('token'),
    ]));

    Fortify::requestPasswordResetLinkView(
        fn (Request $request) => Inertia::render('auth/forgot-password', [
            'status' => $request->session()->get('status'),
        ])
    );

    Fortify::verifyEmailView(
        fn (Request $request) => Inertia::render('auth/verify-email', [
            'status' => $request->session()->get('status'),
        ])
    );

    Fortify::registerView(fn () => Inertia::render('auth/register'));

    Fortify::twoFactorChallengeView(fn () => Inertia::render('auth/two-factor-challenge'));

    Fortify::confirmPasswordView(fn () => Inertia::render('auth/confirm-password'));
}
```

每个视图方法接收一个返回 Inertia 组件的闭包。要点在于使用 `Features::enabled()` 检查功能开关，并传入视图。

<Info>
  在 Blade 应用中，将 `Inertia::render(...)` 替换为 `view('auth.login')` 即可。即便前端不同，只需修改 `FortifyServiceProvider`，认证逻辑保持不变。
</Info>

### 3. 配置限流

```php theme={null}
private function configureRateLimiting(): void
{
    RateLimiter::for('two-factor', function (Request $request) {
        return Limit::perMinute(5)->by($request->session()->get('login.id'));
    });

    RateLimiter::for('login', function (Request $request) {
        $throttleKey = Str::transliterate(
            Str::lower($request->input(Fortify::username())) . '|' . $request->ip()
        );

        return Limit::perMinute(5)->by($throttleKey);
    });
}
```

* `login` 限流器：按邮箱 + IP 的组合限流（防止暴力破解）
* `two-factor` 限流器：以 Session 中登录尝试 ID 限流

`config/fortify.php` 的 `limiters` 键与传给 `RateLimiter::for()` 的键需保持一致。

## 主要功能与注册的路由

按功能整理 Fortify 注册的主要路由。

| 功能         | 方法                        | 路由                                 |
| ---------- | ------------------------- | ---------------------------------- |
| 登录         | `GET`                     | `/login`                           |
| 登录         | `POST`                    | `/login`                           |
| 登出         | `POST`                    | `/logout`                          |
| 注册         | `GET`                     | `/register`                        |
| 注册         | `POST`                    | `/register`                        |
| 密码重置请求     | `GET` / `POST`            | `/forgot-password`                 |
| 密码重置       | `GET` / `POST`            | `/reset-password`                  |
| 邮箱验证       | `GET`                     | `/email/verify`                    |
| 邮箱验证链接重发   | `POST`                    | `/email/verification-notification` |
| 密码确认       | `GET` / `POST`            | `/user/confirm-password`           |
| 启用 2FA     | `POST`                    | `/user/two-factor-authentication`  |
| 2FA 挑战     | `GET` / `POST`            | `/two-factor-challenge`            |
| Passkey 登录 | `GET` / `POST`            | `/passkeys/login`                  |
| Passkey 管理 | `GET` / `POST` / `DELETE` | `/user/passkeys`                   |

可以使用 `php artisan route:list --name=fortify` 或直接 `php artisan route:list` 确认实际注册的路由。

## 二要素认证（2FA）

Starter Kit 中已启用 `Features::twoFactorAuthentication()`。`confirm` 与 `confirmPassword` 都设置为 `true`。

| 选项                | 含义                 |
| ----------------- | ------------------ |
| `confirm`         | 启用后要求用验证码进行确认      |
| `confirmPassword` | 修改 2FA 设置前要求二次输入密码 |

在 2FA 设置页面，用户可以完成以下操作。

<Steps>
  <Step title="启用 2FA">
    向 `/user/two-factor-authentication` 发起 POST 请求。成功后 Session 会置入 `two-factor-authentication-enabled` 状态。
  </Step>

  <Step title="查看二维码">
    向 `/user/two-factor-qr-code` 发起 GET 请求，返回可供认证应用扫描的 SVG 二维码。
  </Step>

  <Step title="用验证码确认">
    向 `/user/confirmed-two-factor-authentication` 发起 POST 提交验证码，完成设置。
  </Step>

  <Step title="保存恢复码">
    向 `/user/two-factor-recovery-codes` 发起 GET 请求，取得恢复码并保存到安全位置。
  </Step>
</Steps>

## Passkey

Passkey 是最近添加到 Fortify 的功能。它是基于 WebAuthn 的无密码认证，支持 Face ID、Touch ID、Windows Hello 与硬件安全密钥。

### 启用

在 `config/fortify.php` 的 `features` 数组中添加：

```php theme={null}
'features' => [
    Features::registration(),
    Features::resetPasswords(),
    Features::emailVerification(),
    Features::twoFactorAuthentication([
        'confirm'         => true,
        'confirmPassword' => true,
    ]),
    Features::passkeys([
        'confirmPassword' => true,
    ]),
],
```

接下来在 `User` 模型上添加 `PasskeyUser` 契约与 `PasskeyAuthenticatable` trait。

```php theme={null}
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Fortify\Contracts\PasskeyUser;
use Laravel\Fortify\PasskeyAuthenticatable;

class User extends Authenticatable implements PasskeyUser
{
    use PasskeyAuthenticatable;
}
```

WebAuthn 配置通过 `config/fortify.php` 的 `passkeys` 键管理。

```php theme={null}
'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,
],
```

<Info>
  Fortify 的 Passkey 在内部封装了 `laravel/passkeys` Composer 包。无需发布 `laravel/passkeys` 的配置文件，`config/fortify.php` 的 `passkeys` 键会优先生效。
</Info>

有关 Passkey 的详细实现（`@laravel/passkeys` JS 客户端、React/Vue/Svelte 辅助方法等），可以一并参考 [Passkey 初步调研](/zh/blog/passkeys-introduction)。

## 相关页面

<Card title="自定义认证 Guard" icon="shield" href="/zh/advanced/custom-auth-guard">
  讲解如何通过实现 Guard、StatefulGuard 接口创建自定义认证 Guard。
</Card>

<Card title="官方文档：Laravel Fortify" icon="book-open" href="https://laravel.com/docs/fortify">
  安装、完整功能、自定义等详细信息请参考官方文档。
</Card>


## Related topics

- [如何创建 Laravel Starter Kit](/zh/advanced/starter-kit-creation.md)
- [从 laravel/ui 迁移到 Fortify 的指南](/zh/blog/ui-to-fortify.md)
- [Feedable](/zh/packages/feedable/index.md)
- [核心包与自定义驱动 - Feedable](/zh/packages/feedable/core.md)
- [Laravel Console Starter](/zh/packages/laravel-console-starter/index.md)
