You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中能否在用户登录会话过期前调用事件?

会话过期时记录用户登出时间的解决方案

方法一:监听Laravel会话过期事件

Laravel内置了Illuminate\Session\Events\SessionExpired事件,可通过监听该事件处理会话过期场景:

  1. 创建监听器
php artisan make:listener SessionExpiredListener
  1. 编写监听器逻辑
    修改生成的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();
            }
        }
    }
}
  1. 注册事件与监听器
    打开app/Providers/EventServiceProvider.php,在$listen数组中添加关联:
protected $listen = [
    // 其他已注册事件...
    \Illuminate\Session\Events\SessionExpired::class => [
        \App\Listeners\SessionExpiredListener::class,
    ],
];

方法二:通过中间件补录过期会话的登出时间

若会话过期事件无法覆盖所有场景,可通过中间件在用户下次访问时补录:

  1. 创建中间件
php artisan make:middleware TrackUserActivity
  1. 编写中间件逻辑
    修改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);
    }
}
  1. 注册中间件
    在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 08:01:06