我正在尝试在用户会话超时时设置自定义消息。我设法设置超时重新路由,但我很难包含一条消息来通知用户。这是我认为相关的部分代码:
composer.json
"require": {
"php": "^8.2",
"laravel/framework": "^11.9",
"laravel/tinker": "^2.9",
"laravel/ui": "^4.5"
},
"require-dev": {
"laravel/breeze": "^2.1"
}
登录.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="{{ mix('style.css') }}">
</head>
<body>
<section>
<div id="form-container">
<form action="{{ route('login.submit') }}" method="POST">
...
</form>
</div>
</section>
@if(session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@else
<p>no problem here.</p>
@endif
</body>
</html>
CheckSessionTimeout.php(中间件)
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class CheckSessionTimeout
{
public function handle(Request $request, Closure $next): Response
{
if (Auth::check()) {
$lastActivityTime = $request->session()->get('lastActivityTime', time());
$sessionTimeout = config('session.lifetime') * 60;
if (time() - $lastActivityTime > $sessionTimeout) {
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('login')->with('error', 'Your session has expired. Please log in again.');
}
$request->session()->put('lastActivityTime', time());
}
return $next($request);
}
}
web.php(路由)
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\RosterController;
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Middleware\CheckSessionTimeout;
require __DIR__.'/auth.php';
Route::get('/login', function () {
return view('login');
})->name('login');
Route::post('/login', [LoginController::class, 'login']
)->name('login.submit');
Route::middleware([CheckSessionTimeout::class])->group(function () {
...
Route::middleware('auth')->group(function () {
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy']
)->name('logout');
});
});
我想简单谈谈我的理想产出和当前结果:
理想:用户会话超时后,下一个请求将始终转到login.php视图,并带有额外消息通知用户会话已超时。
结果:用户确实重定向到login.php,但消息从未显示。
在问这个问题之前我尝试使用 ChatGPT,所有建议是:
会话生命周期配置:我设置了固定的持续时间,并且我可以一致地触发超时。
中间件执行:我一遍又一遍地审查我的中间件代码,并得到ChatGPT的批准。
Session Flash机制:它一直在->flash()和->with()之间提示,我目前使用的是后者
中间件订单:我也一遍又一遍地检查我的代码,没有明显的问题。
在调试每一个步骤并更多地研究 Laravel 函数之后,我了解到会话生命周期结束时的行为,系统会自动注销并清除会话数据,不留下任何东西让我的中间件捕获。
以下是有关会话生存期的配置:
session.php
<?php
use Illuminate\Support\Str;
return [
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false)
];
与我的问题代码相比,唯一有意义的变化是这一行:
CheckSessionTimeout.php
$sessionTimeout = config('session.lifetime') * 60 - 1;
我让我的中间件主动在会话生命周期结束前 1 秒运行会话检查,我的自定义消息最终显示在我的视图中。
希望和我遇到同样问题的人也可以通过这篇参考来解决他们的情况。