Laravel如何通过Fortify处理Socialite用户的2FA校验流程
问题根因
Laravel Fortify自带的2FA校验逻辑仅嵌入在默认账号密码登录的认证管道中。自行实现的Socialite渠道登录回调如果直接调用Auth::login()写入持久化登录态,会完全绕过Fortify的2FA前置校验流程,即使用户已经开启2FA,也会直接跳转至仪表盘。
完整实现步骤
- 调整Socialite渠道的回调登录逻辑,开启2FA的用户不直接写入登录态,而是将用户标识存入Fortify识别的临时会话键中,重定向到官方2FA校验页
替换Microsoft渠道回调中原直接登录的逻辑,参考代码如下:public function handleMicrosoftCallback() { $microsoftUser = Socialite::driver('microsoft')->user(); $user = User::where('email', $microsoftUser->email)->firstOrFail(); // 检测用户是否已开启2FA if ($user->two_factor_secret) { session([ 'login.id' => $user->id, // Fortify默认读取的待校验用户会话键,不可自定义 'login.remember' => false, // 可根据业务需求同步记住我状态 'login.from_socialite' => true // 标记登录来源为Socialite ]); return redirect()->route('two-factor.login'); } // 未开启2FA的用户正常直接登录 Auth::login($user); return redirect()->route('dashboard'); } - 扩展Fortify的2FA登录响应,兼容Socialite来源的登录跳转逻辑
在app/Providers/FortifyServiceProvider.php的boot方法中,绑定自定义的2FA登录响应实现,清理Socialite来源标记,参考代码如下:use Laravel\Fortify\Contracts\TwoFactorLoginResponse; use Illuminate\Support\Facades\Auth; public function boot() { // 原有Fortify配置代码,比如规则、视图配置等保持不变 $this->app->instance(TwoFactorLoginResponse::class, new class implements TwoFactorLoginResponse { public function toResponse($request) { // 清理Socialite来源临时标记 if ($request->session()->has('login.from_socialite')) { $request->session()->forget('login.from_socialite'); } // 校验通过后正常跳转至目标页 return redirect()->intended(route('dashboard')); } }); } - 补充2FA流程的异常退出逻辑,避免临时会话残留导致的登录异常
新增2FA取消登录的逻辑,清理所有临时登录会话,参考代码如下:public function cancelTwoFactorAuth(Request $request) { $request->session()->forget(['login.id', 'login.remember', 'login.from_socialite']); Auth::logout(); return redirect()->route('login'); }
注意事项
- 所有扩展逻辑通过服务容器绑定、会话标记实现,不要直接修改Fortify或Jetstream的核心源码,避免版本升级出现兼容问题
- 临时会话必须使用Fortify默认的
login.id键存储待校验用户ID,自定义键名会导致Fortify无法识别待校验用户,直接重定向回登录页 - 基于Inertia/Vue栈的项目可直接复用Jetstream自带的2FA校验页面,不需要额外开发前端表单,重定向到
two-factor.login路由即可自动渲染 - 相关路由必须放在
web中间件组下,否则会话无法正常存取,2FA流程会失效 - 如果业务需要支持Socialite渠道的"记住我"功能,在存临时会话时同步标记remember状态,2FA校验通过后Fortify会自动按标记生成持久化登录态
内容的提问来源于stack exchange,提问作者Ron
相关产品推荐
相关产品推荐

