跳转到主要内容

什么是 Fortify

Laravel Fortify 是与前端解耦的认证后端实现。它提供了登录、注册、密码重置、邮箱验证、2FA、Passkey 所需的全部路由与 Controller。
Fortify 本身不带 UI。通过从 Starter Kit 或自定义 UI 向 Fortify 的路由发送请求来使用其功能。
「与前端解耦」这一设计理念很重要。无论前端使用 Blade、Inertia(React/Vue/Svelte)还是 API,都可以复用相同的认证后端。这正是 Fortify 长期被使用的原因。

历史:从 Jetstream 到现行 Starter Kit

为什么当前 Starter Kit 也使用 Fortify

最初的 React/Vue Starter Kit 并未使用 Fortify。但在需要支持二要素认证(2FA)时,直接采用 Fortify 使整个认证转向了以 Fortify 为基础。 由于 Fortify 是按「前端无关」的思路设计,与基于 Inertia 的 Starter Kit 契合,因此持续沿用至今。
Fortify 是目前使用时间最长的 Laravel 官方认证包。自 2020 年问世以来,从 Jetstream 到当前 Starter Kit,形态几经变化但始终活跃。

当前 Starter Kit 的构成

React/Vue Starter Kit 中,Fortify 的配置分布在以下文件:
  • app/Providers/FortifyServiceProvider.php — 注册视图、Action、限流
  • config/fortify.php — 启用的功能与认证配置

config/fortify.php 的主要配置

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

private function configureActions(): void
{
    Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
    Fortify::createUsersUsing(CreateNewUser::class);
}
用户创建与密码重置的逻辑通过 app/Actions/Fortify/ 下的类进行自定义。验证与哈希处理都集中在此。

2. 配置视图

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() 检查功能开关,并传入视图。
在 Blade 应用中,将 Inertia::render(...) 替换为 view('auth.login') 即可。即便前端不同,只需修改 FortifyServiceProvider,认证逻辑保持不变。

3. 配置限流

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.phplimiters 键与传给 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
启用 2FAPOST/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()confirmconfirmPassword 都设置为 true
选项含义
confirm启用后要求用验证码进行确认
confirmPassword修改 2FA 设置前要求二次输入密码
在 2FA 设置页面,用户可以完成以下操作。
1

启用 2FA

/user/two-factor-authentication 发起 POST 请求。成功后 Session 会置入 two-factor-authentication-enabled 状态。
2

查看二维码

/user/two-factor-qr-code 发起 GET 请求,返回可供认证应用扫描的 SVG 二维码。
3

用验证码确认

/user/confirmed-two-factor-authentication 发起 POST 提交验证码,完成设置。
4

保存恢复码

/user/two-factor-recovery-codes 发起 GET 请求,取得恢复码并保存到安全位置。

Passkey

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

启用

config/fortify.phpfeatures 数组中添加:
'features' => [
    Features::registration(),
    Features::resetPasswords(),
    Features::emailVerification(),
    Features::twoFactorAuthentication([
        'confirm'         => true,
        'confirmPassword' => true,
    ]),
    Features::passkeys([
        'confirmPassword' => true,
    ]),
],
接下来在 User 模型上添加 PasskeyUser 契约与 PasskeyAuthenticatable trait。
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.phppasskeys 键管理。
'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 的 Passkey 在内部封装了 laravel/passkeys Composer 包。无需发布 laravel/passkeys 的配置文件,config/fortify.phppasskeys 键会优先生效。
有关 Passkey 的详细实现(@laravel/passkeys JS 客户端、React/Vue/Svelte 辅助方法等),可以一并参考 Passkey 初步调研

相关页面

自定义认证 Guard

讲解如何通过实现 Guard、StatefulGuard 接口创建自定义认证 Guard。

官方文档:Laravel Fortify

安装、完整功能、自定义等详细信息请参考官方文档。
最后修改于 2026年7月13日