Laravel 8 + Inertia.js 会话超时提交报419错误 如何跳转登录页
问题根因
你遇到的提交表单419、但GET页面可正常访问的情况,原因有两点:
- Laravel仅对POST/PUT/DELETE等修改类请求校验CSRF Token,会话过期后旧Token失效就会返回419错误;GET请求默认不校验CSRF,所以可以正常加载。
- 你没有配置全局的会话超时校验逻辑,也没有对419异常做自定义处理,所以不会自动跳转到登录页。
解决步骤
1. 修正会话基础配置
先修改.env文件的会话有效期配置,SESSION_LIFETIME单位为分钟,你要10分钟超时就改为:
SESSION_LIFETIME=10
session.php中的expire_on_close参数按需配置,设为true代表关闭浏览器就清空会话,设为false则会按设置的lifetime保留会话。配置修改后执行php artisan config:clear清除配置缓存生效。
2. 添加全局会话超时校验中间件
执行命令创建自定义中间件:php artisan make:middleware CheckSessionTimeout
打开app/Http/Middleware/CheckSessionTimeout.php写入以下逻辑:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Session; class CheckSessionTimeout { public function handle($request, Closure $next) { // 排除登录、登出等公共路由,避免死循环 if ($request->is('login') || $request->is('logout')) { return $next($request); } // 仅登录用户需要校验会话超时 if (Auth::check()) { $lastActivity = Session::get('last_activity'); $timeout = config('session.lifetime') * 60; // 分钟转秒 // 超时则清空会话跳转登录 if (time() - $lastActivity > $timeout) { Auth::logout(); Session::flush(); return $request->inertia() ? redirect()->route('login')->with('message', '会话已超时,请重新登录') : redirect()->route('login'); } // 每次请求更新最后活动时间 Session::put('last_activity', time()); } return $next($request); } }
打开app/Http/Kernel.php,将中间件注册到web中间件组,放在StartSession之后:
protected $middlewareGroups = [ 'web' => [ // ... 其他原有中间件 \Illuminate\Session\Middleware\StartSession::class, \App\Http\Middleware\CheckSessionTimeout::class, // 新增这行 // ... 其他原有中间件 ], ];
3. 自定义处理419 CSRF异常
打开app/Exceptions/Handler.php,修改register方法拦截Token过期异常:
use Illuminate\Session\TokenMismatchException; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Session; public function register() { $this->renderable(function (TokenMismatchException $e, $request) { // 先清空无效会话 Auth::logout(); Session::flush(); // Inertia异步请求返回重定向响应 if ($request->inertia()) { return redirect()->route('login')->with('message', '会话已超时,请重新登录'); } // 普通表单请求直接跳转登录 return redirect()->route('login')->withErrors(['message' => '会话已超时,请重新登录']); }); }
4. 前端适配(可选,体验更流畅)
在前端入口文件resources/js/app.js中添加全局响应拦截,遇到419状态直接跳转登录:
import { Inertia } from '@inertiajs/inertia' Inertia.on('error', (event) => { if (event.detail.response.status === 419) { window.location.href = '/login' } })
内容的提问来源于stack exchange,提问作者Achraf Ben Soltane
相关产品推荐
相关产品推荐

