在Laravel 12中实现登录超时自动退出功能

在Laravel中实现登录超时自动退出功能,可以通过以下两种方式实现(推荐使用复合方案):


方案一:会话生命周期控制(基础版)

核心配置 .env

SESSION_LIFETIME=30    # 会话有效期(分钟)
SESSION_EXPIRE_ON_CLOSE=true  # 关闭浏览器即失效

验证中间件 app/Http/Middleware/CheckSessionTimeout.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class CheckSessionTimeout
{
    public function handle($request, Closure $next)
    {
        // 已登录用户检查最后活动时间
        if (Auth::check()) {
            $lastActive = session('last_active_time');
            $timeout = config('session.lifetime') * 60; // 转换为秒

            if (time() - $lastActive > $timeout) {
                Auth::logout();
                session()->flush();
                return redirect('/login')->with('timeout', '会话已超时,请重新登录');
            }
            
            session(['last_active_time' => time()]); // 更新活动时间戳
        }

        return $next($request);
    }
}

注册中间件 app/Http/Kernel.php

protected $routeMiddleware = [
    // ...
    'session.timeout' => \App\Http\Middleware\CheckSessionTimeout::class,
];

路由应用示例

Route::group(['middleware' => ['auth', 'session.timeout']], function () {
    // 需要登录的受保护路由
});

方案二:复合方案(会话+数据库验证)

扩展用户模型 app/Models/User.php

protected $dates = ['last_activity_at'];

public function checkActivityTimeout($minutes = 30)
{
    return !$this->last_activity_at || 
           $this->last_activity_at->diffInMinutes(now()) > $minutes;
}

活动追踪中间件 app/Http/Middleware/RecordUserActivity.php

public function handle($request, Closure $next)
{
    if (Auth::check()) {
        $user = Auth::user();
        $user->last_activity_at = now();
        $user->save();
    }
    
    return $next($request);
}

组合使用中间件

// 在Kernel.php的web中间件组中添加:
\App\Http\Middleware\RecordUserActivity::class,

// 受保护路由组:
Route::group([
    'middleware' => ['auth', 'session.timeout', 'check.activity:30']
], function() {
    // 需要双重验证的路由
});

方案三:前端自动跳转(配合方案一/二)

JavaScript监听(Blade模板)

let idleTimer;
const timeoutMinutes = {{ config('session.lifetime') }};
const timeoutMs = timeoutMinutes * 60 * 1000;

function resetTimer() {
    clearTimeout(idleTimer);
    idleTimer = setTimeout(logout, timeoutMs);
}

function logout() {
    window.location.href = '/login?timeout=1';
}

// 用户活动监听
document.addEventListener('mousemove', resetTimer);
document.addEventListener('keypress', resetTimer);
resetTimer(); // 初始启动

心跳路由(保持会话活跃)

// routes/web.php
Route::post('/keep-alive', function() {
    return response()->json(['status' => 'active']);
});

// 前端每5分钟发送请求
setInterval(() => {
    fetch('/keep-alive', { method: 'POST' });
}, 5 * 60 * 1000);

安全增强措施

  1. 并发登录控制
// 修改Auth配置 config/auth.php
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
        'hash' => false,
        'expire' => env('SESSION_LIFETIME', 120), // 同步会话时间
    ],
],
  1. 密码修改后全局退出
// 修改密码后调用
Auth::logoutOtherDevices($newPassword);

// 清除所有活动会话
DB::table('sessions')
    ->where('user_id', Auth::id())
    ->delete();

配置验证流程
  1. 测试超时场景
# 临时设置1分钟超时(测试用)
SESSION_LIFETIME=1 php artisan serve
  1. 查看会话表(使用database驱动时)
SELECT * FROM sessions WHERE user_id = {userId}

实现效果说明

  • 多层防御:会话超时+数据库活跃时间验证+前端自动跳转
  • 精准控制:可针对不同用户组设置不同的超时时间
  • 活动追踪:精确记录用户最后操作时间(精确到秒)
  • 安全审计:通过last_last_activity_at字段可进行安全审计

注意‌:生产环境建议使用Redis作为会话驱动以获得最佳性能,同时需要确保服务器时间与客户端时间同步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值