Laravel用户最后活动时间追踪及自动登出问题排查
问题解答
问题1:auth路由组内执行操作时,session的activity_time是否会更新?
会更新。因为你的Authenticate中间件是auth路由组绑定的核心中间件,每次访问该组内的路由时,都会触发中间件的handle方法:
- 已登录用户的
auth()->check()会返回true,因此会执行session()->put('activity_time', now()->toDateTimeString()),覆盖旧的session值。 - 只要请求进入auth路由组,这个更新逻辑就会触发,所以每次操作都会刷新最后活动时间。
问题2:CheckLastActivityTime中间件中$lastActivity为null的原因及解决方案
原因分析
你把CheckLastActivityTime注册到了全局$middleware数组中,但Laravel的全局中间件执行顺序早于StartSession中间件(负责加载和初始化session)。当该中间件运行时,session还未启动,自然无法获取到activity_time的值,所以返回null。
正确实现步骤
1. 调整中间件注册位置
将CheckLastActivityTime从全局$middleware移到web中间件组,且放在StartSession和Authenticate之后,确保session已加载、用户身份已验证:
// app/Http/Kernel.php protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, \App\Http\Middleware\Authenticate::class, \App\Http\Middleware\CheckLastActivityTime::class, // 移到此处 ], ];
2. 拆分活动时间更新逻辑
不建议在Authenticate中间件中混入更新逻辑,新建一个UpdateActivityTime中间件专门处理活动时间刷新:
// app/Http/Middleware/UpdateActivityTime.php <?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class UpdateActivityTime { public function handle(Request $request, Closure $next) { if (auth()->check()) { session()->put('activity_time', now()->toDateTimeString()); } return $next($request); } }
将其注册到web中间件组的CheckLastActivityTime之后(先检查超时,再更新最新时间,避免逻辑冲突):
// app/Http/Kernel.php -> web中间件组 \App\Http\Middleware\CheckLastActivityTime::class, \App\Http\Middleware\UpdateActivityTime::class, // 新增
3. 修正CheckLastActivityTime中间件细节
补充未登录用户跳过检查、首次登录初始化时间的逻辑:
// app/Http/Middleware/CheckLastActivityTime.php <?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Carbon\Carbon; class CheckLastActivityTime { public function handle(Request $request, Closure $next) { // 未登录用户直接跳过 if (!auth()->check()) { return $next($request); } $lastActivity = session()->get('activity_time'); // 首次登录时初始化活动时间 if (!$lastActivity) { session()->put('activity_time', now()->toDateTimeString()); return $next($request); } $lastActivityTime = Carbon::parse($lastActivity); if (Carbon::now()->diffInMinutes($lastActivityTime) > 5) { auth()->logout(); session()->invalidate(); session()->regenerateToken(); return redirect()->route('root')->with('error', '会话已过期,请重新登录。'); } return $next($request); } }
4. 确认路由中间件配置
确保Kernel.php的$routeMiddleware中存在auth绑定:
protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, // ... 其他中间件 ];
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

