news 2026/9/6 23:07:24

Coolify 中的 Laravel Fortify 认证体系:配置项、可覆盖 Action 与关键端点实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Coolify 中的 Laravel Fortify 认证体系:配置项、可覆盖 Action 与关键端点实战解析

Coolify 中的 Laravel Fortify 认证体系:配置项、可覆盖 Action 与关键端点实战解析

【免费下载链接】coolifyAn open-source, self-hostable PaaS alternative to Vercel, Heroku & Netlify that lets you easily deploy static sites, databases, full-stack applications and 280+ one-click services on your own servers.项目地址: https://gitcode.com/GitHub_Trending/co/coolify

本篇以 Coolify 仓库中的开发技能文档 .agents/skills/fortify-development/SKILL.md 为主体,系统讲解 Laravel Fortify 作为"无前端(headless)认证后端"在 Coolify 中的落地方式:如何通过 config/fortify.php 启用功能特性、如何在app/Actions/Fortify/下覆盖用户创建与密码逻辑、如何用FortifyServiceProvider注册视图回调与响应契约,以及登录限流在 RouteServiceProvider 中的真实实现。读完后你可以完整掌握 Fortify 的端点清单、各功能的启用条件,并具备在自有 Laravel 项目中复用同一套认证架构的能力。

什么是 Fortify:无前端认证后端

Fortify 是一个 headless 的认证后端,它为 Laravel 应用注册认证所需的全部路由与控制器(登录、注册、密码重置、邮箱验证、两步验证、Passkey 等),但不绑定任何前端视图——界面由应用自己通过"视图回调"提供。这一设计使 Fortify 既能驱动传统 Blade 页面,也能驱动 Livewire、SPA 或纯 API 客户端。

Coolify 正是这一模式的典型使用者:

  • 认证路由与控制器由 Fortify 包注册(登录、登出、注册、忘记密码、两步验证挑战等);
  • 视图层由 app/Providers/FortifyServiceProvider.php 中的Fortify::loginView()Fortify::registerView()等回调绑定到 Coolify 自有的 Blade 页面(如auth.loginauth.register);
  • 业务逻辑(用户创建、密码重置、资料更新)集中在 app/Actions/Fortify/ 目录下的四个类中,通过契约(Contracts)注入。

从源码结构看,Fortify 的扩展点可归纳为五类:路由/端点(包内注册)、Actions(可覆盖的业务逻辑)、Config(特性开关与全局选项)、Contracts(可覆盖的响应类,如LoginResponseLogoutResponseRegisterResponse)、视图回调(在FortifyServiceProvider::boot()中设置)。

核心配置:config/fortify.php 逐项解读

Coolify 的 config/fortify.php 展示了 Fortify 的全部关键配置段,实际取值如下:

配置项Coolify 取值作用
guardwebFortify 认证所用的 guard,必须与 config/auth.php 中的某个 guard 对应;SPA 会话认证模式下必须为web
passwordsusers密码重置使用的 broker,对应auth.php中的 password broker
username/email均为email"用户名"字段所用的模型属性;也决定忘记密码/重置请求中预期的字段名
homeRouteServiceProvider::HOME登录或重置成功后的跳转路径
prefix/domain''/null所有 Fortify 路由的前缀与子域名,Coolify 使用无前缀默认
middleware['web']Fortify 路由挂载的中间件组
limiterslogintwo-factorforgot-password登录、两步验证挑战、忘记密码使用的限流器名称
viewstrue是否启用返回视图的路由;SPA 项目可设为false只保留 JSON 接口
features见下文功能特性开关数组

features数组是 Fortify 的功能总开关,可用的特性有:

  • Features::registration()— 用户注册;
  • Features::resetPasswords()— 通过邮箱重置密码;
  • Features::emailVerification()— 邮箱验证(要求User实现MustVerifyEmail接口);
  • Features::updateProfileInformation()— 更新个人资料;
  • Features::updatePasswords()— 修改密码;
  • Features::twoFactorAuthentication()— 两步验证(TOTP,带二维码与恢复码),可附加选项;
  • Features::passkeys()— 基于 WebAuthn 的 Passkey 无密码认证。

Coolify 当前启用了其中五项(config/fortify.php):

'features' => [ Features::registration(), Features::resetPasswords(), // Features::emailVerification(), Features::updateProfileInformation(), Features::updatePasswords(), Features::twoFactorAuthentication([ 'confirm' => true, 'confirmPassword' => true, // 'window' => 0, ]), ],

两点值得注意:

  1. 邮箱验证特性被注释掉了。从源码看,Coolify 没有让User实现MustVerifyEmail(app/Models/User.php 仅实现了SendsEmail接口),而是用自建流程替代:自托管部署时用户创建后直接调用markEmailAsVerified(),云版本则派发SendVerificationEmailJob(见下文CreateNewUser分析)。
  2. 两步验证启用了confirm => trueconfirmPassword => true:前者要求用户在启用 2FA 后通过"确认"步骤二次认证,后者在敏感操作前要求再次输入密码。confirm选项还会联动数据库迁移——见下文 2FA 章节。

关键端点清单

Fortify 注册的完整端点(按功能特性启用与否而定)如下,这是排查认证问题时最常用的一张表:

功能方法端点
登录POST/login
登出POST/logout
注册POST/register
请求密码重置POST/forgot-password
执行密码重置POST/reset-password
邮箱验证通知GET/email/verify
重发验证邮件POST/email/verification-notification
密码确认POST/user/confirm-password
启用 2FAPOST/user/two-factor-authentication
确认 2FAPOST/user/confirmed-two-factor-authentication
2FA 挑战POST/two-factor-challenge
获取二维码GET/user/two-factor-qr-code
恢复码GET/POST/user/two-factor-recovery-codes
Passkey 登录选项GET/passkeys/login/options
Passkey 登录POST/passkeys/login
Passkey 确认选项GET/passkeys/confirm/options
Passkey 确认POST/passkeys/confirm
Passkey 选项GET/user/passkeys/options
注册 PasskeyPOST/user/passkeys
删除 PasskeyDELETE/user/passkeys/{passkey}

开发时可以用php artisan route:list(或技能文档中提到的list-routes --only-vendor方式)按Fortify控制器筛选,快速确认哪些端点在当前特性配置下实际可用。

Actions 层:四个可覆盖的业务逻辑类

Fortify 把认证流程中的业务动作抽象成契约(Contracts),应用侧在app/Actions/Fortify/提供实现并在 Provider 中注入。Coolify 实现了四个:

CreateNewUser:注册逻辑的重灾区

app/Actions/Fortify/CreateNewUser.php 实现CreatesNewUsers契约,它包含了三块 Coolify 定制逻辑:

(1)注册开关与双重限流。注册前先检查实例级开关,再执行自定义限流:

private const REGISTRATION_IP_MAX_ATTEMPTS = 3; private const REGISTRATION_IP_DECAY_SECONDS = 600; private const REGISTRATION_EMAIL_IDENTITY_MAX_ATTEMPTS = 3; private const REGISTRATION_EMAIL_IDENTITY_DECAY_SECONDS = 3600;
  • is_registration_enabled为 false 时直接abort(403)
  • IP 维度registration:ip:{sha1(ip)})10 分钟内最多 3 次,超限abort(429)
  • 归一化邮箱身份维度(registration:email-identity:{sha1(...)})1 小时内最多 3 次。normalize_email_identity()辅助函数可剥离+别名等变体,防止"同一个人换邮箱后缀"绕过限制。

(2)首个用户即 root 用户。当数据库中尚无任何用户时,新用户以id => 0强制填充(forceFill),挂载到预先由 seeder 创建好的 Root Team(Team::find(0))并赋予owner角色;创建完成后立即关闭注册开关is_registration_enabled = false),保证自托管实例只有第一个注册用户。

(3)邮箱验证策略分流。非首个用户的处理因部署形态而异:

if (isCloud()) { SendVerificationEmailJob::dispatch($user); } else { $user->markEmailAsVerified(); }

验证邮件由 User::sendVerificationEmail() 发出,链接使用URL::temporarySignedRoute('verify.verify', ...)生成的临时签名路由,有效期取自config('auth.verification.expire', 60)(分钟)。

其余三个 Action

  • ResetUserPassword.php(实现ResetsUserPasswords):校验新密码满足Password::defaults()confirmed,写入后调用$user->deleteAllSessions()撤销所有已签发会话——这正是"重置密码后其他设备掉线"的来源;
  • UpdateUserPassword.php(实现UpdatesUserPasswords):要求current_password通过current_password:web校验(即对照webguard 的当前密码),新密码同样要求Password::defaults()+confirmed,错误信息使用updatePassword校验 bag;
  • UpdateUserProfileInformation.php(实现UpdatesUserProfileInformation):校验nameemailRule::unique('users')->ignore($user->id));若用户实现了MustVerifyEmail且邮箱变更,则清空email_verified_at并重新发送验证通知,否则直接落库。

FortifyServiceProvider:视图回调与响应契约

app/Providers/FortifyServiceProvider.php 是 Coolify 定制 Fortify 行为的核心文件,分为register()boot()两部分。

register():覆盖 RegisterResponse 契约

Fortify 的认证响应通过Laravel\Fortify\Contracts\下的契约类定义,可在容器中用自定义实例替换。Coolify 覆盖了RegisterResponse

$this->app->instance(RegisterResponse::class, new class implements RegisterResponse { public function toResponse($request) { // First user (root) will be redirected to /settings instead of / on registration. if ($request->user()->currentTeam->id === 0) { return redirect()->route('settings.index'); } return redirect(RouteServiceProvider::HOME); } });

即:首个用户(root,属于id = 0的 Root Team)注册完成后被导向/settings完成实例初始化,其余用户回首页。同理,LoginResponseLogoutResponse等契约也可按同样方式覆盖以实现自定义跳转。

boot():视图回调与自定义认证

boot()中依次完成:

  1. 注入 ActionsFortify::createUsersUsing(CreateNewUser::class)Fortify::resetUserPasswordsUsing(...)Fortify::updateUserProfileInformationUsing(...)Fortify::updateUserPasswordsUsing(...)
  2. 注册视图回调
    • Fortify::registerView()— 先检查instanceSettings()->is_registration_enabled,关闭则重定向到登录页;否则渲染auth.register,并传入isFirstUserUser::count() === 0)标志;
    • Fortify::loginView()— 若系统中尚无任何用户,直接重定向到注册页;否则渲染auth.login,并传入注册开关与已启用的 OAuth 供应商列表(OauthSetting::where('enabled', true));
    • Fortify::requestPasswordResetLinkView()/Fortify::resetPasswordView()— 分别绑定auth.forgot-passwordauth.reset-password
    • Fortify::confirmPasswordView()/Fortify::twoFactorChallengeView()— 绑定密码确认与 2FA 挑战页。
  3. Fortify::authenticateUsing()自定义认证管线。这是 Coolify 最重量级的定制点(FortifyServiceProvider.php#L73-L104):
Fortify::authenticateUsing(function (Request $request) { $email = strtolower($request->email); $user = User::where('email', $email)->with('teams')->first(); if ($user && Hash::check($request->password, $user->password)) { // ... } });

其内部还处理了团队邀请的自动接受:如果该邮箱存在一个未过期且有效的TeamInvitation,用户首次登录时会被自动附加到被邀请的团队(携带邀请中的role),currentTeam设为该团队并删除邀请记录;否则走正常流程——取personal_team作为当前团队,缺失时通过recreate_personal_team()重建。最后将currentTeam写入 session。由于 User 模型 的setEmailAttribute会把邮箱统一小写化,这里的strtolower与之配合保证大小写不一致时也能登录成功。

功能特性启用的完整工作流

以下工作流清单继承自技能文档,并结合 Coolify 仓库中的实际文件标注了每一步的落点。

两步验证(2FA)

  • User模型添加TwoFactorAuthenticatable特性 —— Coolify 中位于 app/Models/User.php 的use列表;
  • config/fortify.phpfeatures中启用Features::twoFactorAuthentication()(Coolify 附带confirm => trueconfirmPassword => true);
  • 若缺少*_add_two_factor_columns_to_users_table.php迁移,执行php artisan vendor:publish --tag=fortify-migrations后再migrate
  • FortifyServiceProvider中设置Fortify::twoFactorChallengeView()(Coolify 已绑定auth.two-factor-challenge);
  • 构建 2FA 管理界面(启用/禁用、恢复码展示);
  • 测试二维码扫码与恢复码登录流程。

Coolify 仓库中已内置对应迁移 database/migrations/2014_10_12_200000_add_two_factor_columns_to_users_table.php:无条件添加可空的two_factor_secrettwo_factor_recovery_codes两列;仅当Fortify::confirmsTwoFactorAuthentication()为真时才添加two_factor_confirmed_at——这解释了为何 config 中的confirm选项会直接影响数据库结构。User模型也在$hidden中隐藏了two_factor_secrettwo_factor_recovery_codes,防止敏感字段随 API 序列化泄露。

Passkey(WebAuthn)

  • User模型添加PasskeyAuthenticatable特性并实现PasskeyUser接口;
  • config/fortify.php启用Features::passkeys()
  • 若缺少 passkeys 表迁移,php artisan vendor:publish --tag=fortify-migrations并迁移;
  • 按需配置relying_party_idallowed_originsuser_handle_secrettimeout等参数(默认值不适合生产时);
  • 基于@laravel/passkeys前端包构建注册、登录、确认、删除四种交互界面。

Coolify 当前 config/fortify.php 的features中未启用该特性,即 Passkey 相关端点(/passkeys/login等)处于未注册状态。

邮箱验证

  • 在 config 中启用Features::emailVerification()
  • User模型实现MustVerifyEmail接口;
  • 设置verifyEmailView回调;
  • 在受保护路由上挂verified中间件;
  • 测试"注册 → 收信 → 点击验证链接"完整流程。

再次强调 Coolify 的特殊性:它刻意没有启用这一 Fortify 特性(config 中被注释),而是自实现了"自托管即验证、云版本异步验证邮件"的分支逻辑,并额外提供了邮箱变更验证流程(pending_email+ 6 位验证码 + 过期时间,见 User::requestEmailChange())。

密码重置

  • 启用Features::resetPasswords()
  • 设置requestPasswordResetLinkView回调(Coolify:auth.forgot-password);
  • 设置resetPasswordView回调(Coolify:auth.reset-password);
  • 若禁用了视图,需自行定义password.reset命名路由;
  • 测试"申请重置 → 收信 → 链接重置"全流程。

重置邮件由 User::sendPasswordResetNotification() 发出,委托给TransactionalEmails\ResetPassword通知类。

SPA 模式('views' => false

  • config/fortify.php中设置'views' => false
  • 安装并配置 Laravel Sanctum 以支撑基于会话的 SPA 认证;
  • 确保使用webguard(会话认证的前提);
  • 配置好 CSRF 令牌处理;
  • 测试 XHR 认证流程。

viewsfalse时,Fortify 一律返回 JSON 而非重定向。典型场景是 2FA 挑战:若已启用两步验证的用户发起登录,登录请求会返回:

{ "two_factor": true }

前端据此切换到"输入 TOTP 码 / 恢复码"的挑战界面,随后向/two-factor-challenge提交。

限流体系:从 limiters 配置到真实实现

技能文档指出:限流通过fortify.limiters.login等配置项指定限流器名称,默认按"用户名 + IP"组合节流。Coolify 的完整链路是两段式:

第一段:config/fortify.php 声明名称映射:

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

第二段:RouteServiceProvider::configureRateLimiting() 给出每个限流器的真实策略:

RateLimiter::for('login', function (Request $request) { return Limit::perMinute(5)->by((string) $request->email.'|'.auth_rate_limit_ip($request)); }); RateLimiter::for('two-factor', function (Request $request) { return Limit::perMinute(5)->by($request->session()->get('login.id')); });
  • login:每个"邮箱 | IP"组合每分钟最多 5 次——即技能文档所说的 username + IP 组合节流,auth_rate_limit_ip()辅助函数统一取 IP(可适配代理头);
  • two-factor:按 session 中暂存的login.id计数,每分钟 5 次,避免 2FA 挑战接口被暴力猜测 TOTP 码;
  • forgot-password:双重限流——IP 维度 10 分钟 3 次 + 归一化邮箱身份维度每小时 3 次,与注册限流的"邮箱身份"思路一脉相承;
  • 同文件还有magic-linkforce-password-reset等 Coolify 自定义限流器,供非 Fortify 路由使用。

此外,CreateNewUser内的注册限流是独立于上述 limiters 的第三层防护(因为注册失败路径不经过 Fortify 的限流中间件),用RateLimiter::tooManyAttempts()/RateLimiter::hit()手动计数,详见上文。

最佳实践速查

技能文档给出的三条最佳实践,在 Coolify 中均有对应实例:

  1. 自定义认证逻辑:用Fortify::authenticateUsing()覆盖用户检索方式(Coolify 借此实现了邮箱小写化 + 邀请自动接受),用Fortify::authenticateThrough()定制认证管线;用AppServiceProvider中的契约绑定覆盖响应跳转(Coolify 选择在FortifyServiceProvider::register()中覆盖RegisterResponse);
  2. 注册定制:直接修改app/Actions/Fortify/CreateNewUser.php来调整验证规则与附加字段——Coolify 在其中加入了注册开关、双维限流、root 用户初始化与邮箱验证分流;
  3. 限流配置:通过fortify.limiters.login换绑限流器名称,并在RouteServiceProvider中调整阈值与计数键。

小结

Fortify 在 Coolify 中的定位是"路由与认证管线的提供者,而非界面的提供者":config/fortify.php决定开启哪些能力与端点,app/Actions/Fortify/四个类承载可替换的业务规则,FortifyServiceProvider负责把视图、Action 与响应契约接到 Coolify 自己的团队(Team)模型上。理解这三层扩展点,即可在不改动 Fortify 包源码的前提下,完成登录跳转定制、注册策略收紧、2FA/Passkey 启用与限流策略调整等常见需求。涉及 TOTP 实现细节、恢复码处理、Passkey 配置项等更深入的包内机制,可进一步查阅 Laravel Fortify 官方文档与包源码。

【免费下载链接】coolifyAn open-source, self-hostable PaaS alternative to Vercel, Heroku & Netlify that lets you easily deploy static sites, databases, full-stack applications and 280+ one-click services on your own servers.项目地址: https://gitcode.com/GitHub_Trending/co/coolify

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 23:06:45

理解AI创作边界:从技术原理到应对无法生成内容的策略

简介:《当代中国社会阶层研究报告》是一份系统剖析1978年经济改革以来中国社会阶层结构变迁的社会学文献,面向社会学研究者、政策分析者及关注社会分层议题的高校师生。报告基于职业分化和组织资源、经济资源、文化技术资源占有情况,提出十大…

作者头像 李华
网站建设 2026/9/6 23:00:17

AI爆发:从“实验室”到“万物智能”,算力需求“指数级膨胀”

目录 一、AI爆发:从“实验室”到“万物智能”,算力需求“指数级膨胀” 二、CPU/GPU的“力不从心”:不是“不够快”,而是“不对口” 1. CPU:“串行思维”不适合AI的“并行狂欢”​ 2. GPU:“通用并行”但“功耗和成本太高”​ 三、NPU的“天生优势”:为AI神经网络“…

作者头像 李华
网站建设 2026/9/6 22:58:13

Deep-Live-Cam 快速上手:如何用 1 张照片搞定实时换脸

Deep-Live-Cam 快速上手:如何用 1 张照片搞定实时换脸 【免费下载链接】Deep-Live-Cam real time face swap and one-click video deepfake with only a single image 项目地址: https://gitcode.com/GitHub_Trending/de/Deep-Live-Cam Deep-Live-Cam 是一款…

作者头像 李华
网站建设 2026/9/6 22:58:05

论文降重服务避坑指南:识别风险信号与建立可控修改流程

引言 毕业论文写作中,降重与文本改写几乎是每位同学都会遇到的环节。然而,市面上的降重服务良莠不齐,选错服务不仅浪费金钱,更可能让论文质量大打折扣,甚至触碰学术诚信红线。本文将从风险信号识别、修改稿核对、返工…

作者头像 李华
网站建设 2026/9/6 22:55:55

过山车车速控制系统设计:从建模到PID参数整定全解析

简介:面向自动化专业课程设计的《自动控制原理大作业~过山车车速系统设计》文档,围绕过山车车速控制系统的建模与分析展开。资源以直流电动机为驱动、测速发电机为反馈,完整呈现电枢控制直流伺服电动机与测速发电机的微分方程、传递函数推导&…

作者头像 李华