Laravel 9会话超时后无法触发重定向逻辑问题求助
问题分析
你的中间件超时判断逻辑从未执行,核心原因是Laravel自带的会话过期机制会先于你的中间件销毁会话:当用户长时间无操作,Laravel的StartSession中间件会检测到会话过期并清空会话数据,此时Auth::check()返回false,导致你的超时判断if块永远无法触发。你看到的自动登出是Laravel的Authenticate中间件检测到未登录后触发的跳转,而非你的中间件逻辑。
解决方案
1. 调整中间件执行顺序
在app/Http/Kernel.php的web中间件组中,将CheckSessionTimeout放在StartSession之后、Authenticate之前,确保在Laravel自动销毁会话前,你的中间件能先检查空闲时间:
protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \App\Http\Middleware\CheckSessionTimeout::class, // 新增位置 \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
2. 修改中间件逻辑
优化代码逻辑,确保在会话未被Laravel销毁前检测空闲超时,并手动控制登出与跳转:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; class CheckSessionTimeout { public function handle($request, Closure $next) { // 仅对已登录用户处理 if (Auth::check()) { $maxIdleTime = config('session.lifetime') * 60; // 读取最后活动时间,默认值为当前时间(首次登录时) $lastActivity = $request->session()->get('lastActivityTime', time()); // 判断是否超过空闲时间 if (time() - $lastActivity > $maxIdleTime) { // 设置会话超时标记 $request->session()->put('sessionTimedOut', true); // 手动登出用户 Auth::logout(); // 销毁当前会话并生成新的CSRF令牌 $request->session()->invalidate(); $request->session()->regenerateToken(); // 跳转到登录页,可自定义提示信息 return redirect()->route('login')->with('error', '会话已超时,请重新登录'); } // 更新最后活动时间 $request->session()->put('lastActivityTime', time()); } return $next($request); } }
3. 测试验证
临时缩短会话生命周期来快速测试:在.env文件中设置SESSION_LIFETIME=1(表示1分钟超时),登录后等待1分钟再操作,就能触发你的中间件逻辑。
内容的提问来源于stack exchange,提问作者user761100
相关产品推荐
相关产品推荐

