Laravel Jetstream如何实现禁止用户多设备同时登录
Laravel 8 + Jetstream 实现单设备登录解决方案
你的代码不生效主要有两个核心原因:一是缺少必要的中间件支持,二是logoutOtherDevices的调用时机错误。
第一步:开启会话认证中间件
logoutOtherDevices方法依赖AuthenticateSession中间件实现多设备踢下线逻辑,该中间件默认在Laravel中是注释状态,需要手动开启。
修改app/Http/Kernel.php文件,找到web中间件组,取消对应中间件的注释:
protected $middlewareGroups = [ 'web' => [ // 其他原有中间件保持不变 \Illuminate\Session\Middleware\AuthenticateSession::class, ], ];
第二步:调整logoutOtherDevices调用时机
你之前在Fortify::authenticateUsing闭包中调用该方法时,用户尚未完成正式登录流程,新的会话还未生成,调用会出现无效甚至误踢当前新登录设备的问题。建议通过监听登录事件的方式实现,兼容性更强:
修改app/Providers/EventServiceProvider.php,在boot方法中添加如下代码:
public function boot() { // 其他原有代码保持不变 \Event::listen(\Illuminate\Auth\Events\Login::class, function ($event) { // 登录成功后销毁该用户其他所有设备的登录状态 \Auth::logoutOtherDevices(request()->password); }); }
额外适配:开启双因素认证的场景
如果你启用了Jetstream的双因素认证功能,双因素验证步骤的请求中不会携带密码,需要额外调整:
- 在
FortifyServiceProvider.php的authenticateUsing闭包中,先将明文密码暂存到Session:
Fortify::authenticateUsing(function (Request $request) { $user = User::where('email', $request->email)->first(); if ($user && Hash::check($request->password, $user->password)) { // 暂存密码到Session,双因素验证通过后使用 session()->put('temp_login_password', $request->password); return $user; } });
- 调整
Login事件监听的逻辑,从Session中取密码:
\Event::listen(\Illuminate\Auth\Events\Login::class, function ($event) { $password = session()->pull('temp_login_password', request()->password); \Auth::logoutOtherDevices($password); });
最后验证
配置完成后执行php artisan config:clear清空配置缓存,用两个不同浏览器测试:第二个设备登录成功后,刷新第一个设备的页面会自动跳转到登录页,即为配置成功。
内容的提问来源于stack exchange,提问作者Bips
相关产品推荐
相关产品推荐

