You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:09:37