Laravel中会话闲置超时后LogSuccessfulLogout监听器未触发
会话超时自动登出不触发Logout监听器的问题解决
问题根源
Laravel的会话闲置超时是被动机制——只有用户发起新请求时,系统才会发现会话已过期并清除数据,但这个过程不会主动触发Illuminate\Auth\Events\Logout事件。而手动登出时,Auth::logout()方法会主动触发该事件,所以你的LogSuccessfulLogout监听器能正常工作。
解决步骤
1. 生成检测会话超时的中间件
执行Artisan命令创建中间件:
php artisan make:middleware CheckSessionTimeout
2. 编写中间件逻辑
打开app/Http/Middleware/CheckSessionTimeout.php,替换为以下代码:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; use Illuminate\Auth\Events\Logout; class CheckSessionTimeout { public function handle($request, Closure $next) { if (Auth::check()) { $lastActivity = session('last_activity'); $sessionLifetime = config('session.lifetime') * 60; // 更新当前请求的最后活动时间 session(['last_activity' => time()]); // 判断会话是否已超时 if ($lastActivity && (time() - $lastActivity) > $sessionLifetime) { // 手动触发Logout事件,让监听器捕获 event(new Logout(Auth::user())); // 执行登出操作 Auth::logout(); // 重定向到登录页(可根据需求调整) return redirect()->route('login')->with('message', '会话已超时,请重新登录'); } } return $next($request); } }
3. 注册中间件
在app/Http/Kernel.php的web中间件组中,把刚创建的中间件加到StartSession之后:
protected $middlewareGroups = [ 'web' => [ // ...其他已有的中间件 \App\Http\Middleware\StartSession::class, \App\Http\Middleware\CheckSessionTimeout::class, // ...其他已有的中间件 ], ];
4. 初始化最后活动时间
在用户登录成功时,初始化会话的last_activity值。可以在app/Http/Controllers/Auth/LoginController.php中添加authenticated方法:
protected function authenticated(Request $request, $user) { session(['last_activity' => time()]); }
这样配置后,用户每次发起请求时,系统都会检测会话是否超时。一旦超时,就会触发Logout事件,你的LogSuccessfulLogout监听器就能正常记录日志了。
内容的提问来源于stack exchange,提问作者Adnan Rasheed
相关产品推荐
相关产品推荐

