Laravel会话超时后访问受保护路由抛出Attempt to read property "headers" on null异常
问题场景
Laravel 9.41.0 + PHP 8.1环境下,当默认会话超时后,访问任何受auth中间件保护的路由时,会抛出Attempt to read property 'headers' on null异常,且系统未跳转至已定义的登录路由。异常触发于VerifyCsrfToken中间件的addCookieToResponse方法,具体路径为C:\wamp-new\www\twicterminal.com\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\VerifyCsrfToken.php第191行,代码为$response->headers->setCookie($this->newCookie($request, $config));。
核心原因
会话超时后,auth中间件本应返回重定向至登录页的响应,但实际流程中VerifyCsrfToken中间件拿到的$response为null,导致调用headers属性时触发异常,通常是中间件执行逻辑异常或响应传递环节出错导致。
可行解决方案
1. 检查自定义Authenticate中间件逻辑
如果你修改过默认的app/Http/Middleware/Authenticate.php,确保其handle方法在用户未认证时始终返回有效的重定向响应,而非null。默认逻辑示例:
protected function redirectTo($request) { if (! $request->expectsJson()) { return route('login'); } }
若该方法返回null或未正确指向登录路由,会导致auth中间件无有效响应输出,进而让VerifyCsrfToken拿到null。
2. 重写VerifyCsrfToken中间件增加空值校验
直接修改vendor文件不可靠,应在项目内的app/Http/Middleware/VerifyCsrfToken.php中重写addCookieToResponse方法,增加$response的空值判断:
protected function addCookieToResponse($request, $response) { if (is_null($response)) { return $response; } $config = config('session'); if ($this->shouldAddXsrfTokenCookie()) { $response->headers->setCookie($this->newCookie($request, $config)); } return $response; }
这样即使$response为null,也不会触发属性读取异常,同时不影响正常流程。
3. 确认中间件执行顺序
检查路由的中间件定义,确保web中间件组(包含VerifyCsrfToken)在auth中间件之前执行,示例正确写法:
Route::middleware(['web', 'auth'])->group(function () { // 受保护的路由 });
若auth在web之前,可能导致会话超时后auth先返回重定向,但web组的VerifyCsrfToken仍尝试处理空响应,调整顺序即可避免。
4. 排查Session配置异常
检查config/session.php中的配置:
- 确认
driver配置正常(如file、database),且对应存储目录/数据库具备读写权限 - 检查
lifetime、expire_on_close等超时配置是否符合预期 - 尝试清除会话存储(如删除
storage/framework/sessions下的所有文件),排除损坏的会话文件导致的异常
内容的提问来源于stack exchange,提问作者Muhammad Ismail

