Laravel中能否在用户登录会话过期前调用事件?
会话过期时记录用户登出时间的解决方案
方法一:监听Laravel会话过期事件
Laravel内置了Illuminate\Session\Events\SessionExpired事件,可通过监听该事件处理会话过期场景:
- 创建监听器
php artisan make:listener SessionExpiredListener
- 编写监听器逻辑
修改生成的app/Listeners/SessionExpiredListener.php:
<?php namespace App\Listeners; use App\UserTrack; use Carbon\Carbon; use Illuminate\Session\Events\SessionExpired; class SessionExpiredListener { public function handle(SessionExpired $event) { // 从会话中获取用户认证ID,键名需根据实际环境调整 $userId = $event->session->get('login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d'); if ($userId) { $track = UserTrack::where('user_id', $userId) ->orderBy('id', 'desc') ->first(); if ($track && is_null($track->last_logout)) { $end = Carbon::now(); $start = Carbon::parse($track->last_login); $track->last_logout = $end; $track->timestamp = $start->diffInSeconds($end); $track->save(); } } } }
- 注册事件与监听器
打开app/Providers/EventServiceProvider.php,在$listen数组中添加关联:
protected $listen = [ // 其他已注册事件... \Illuminate\Session\Events\SessionExpired::class => [ \App\Listeners\SessionExpiredListener::class, ], ];
方法二:通过中间件补录过期会话的登出时间
若会话过期事件无法覆盖所有场景,可通过中间件在用户下次访问时补录:
- 创建中间件
php artisan make:middleware TrackUserActivity
- 编写中间件逻辑
修改app/Http/Middleware/TrackUserActivity.php:
<?php namespace App\Http\Middleware; use App\UserTrack; use Carbon\Carbon; use Closure; use Illuminate\Support\Facades\Auth; class TrackUserActivity { public function handle($request, Closure $next) { if (Auth::check()) { // 用户已登录,更新活跃时间(可选) $track = UserTrack::where('user_id', Auth::id()) ->whereNull('last_logout') ->orderBy('id', 'desc') ->first(); if ($track) { $track->last_activity = Carbon::now(); $track->save(); } } else { // 用户未登录,检查会话残留的用户ID,补录登出时间 $userId = $request->session()->get('login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d'); if ($userId) { $track = UserTrack::where('user_id', $userId) ->whereNull('last_logout') ->orderBy('id', 'desc') ->first(); if ($track) { $end = Carbon::now(); $start = Carbon::parse($track->last_login); $track->last_logout = $end; $track->timestamp = $start->diffInSeconds($end); $track->save(); $request->session()->forget('login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d'); } } } return $next($request); } }
- 注册中间件
在app/Http/Kernel.php的web中间件组中添加:
protected $middlewareGroups = [ 'web' => [ // 其他已注册中间件... \App\Http\Middleware\TrackUserActivity::class, ], ];
关键注意事项
- 会话中的用户认证键名(如
login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d)可能因Laravel版本、配置不同变化,可通过dd(session()->all())在用户登录后查看实际键名。 - 确保
UserTrack模型的last_logout字段允许为null,用于区分未完成登出记录。 - 两种方法可结合使用,覆盖主动登出和会话过期两种场景。
内容的提问来源于stack exchange,提问作者Prajakta Kate
相关产品推荐
相关产品推荐

