Laravel生产环境出现页面过期错误(Error: 'The page has expired due to inactivity')
解决Laravel生产环境「页面因长时间未操作已过期」CSRF问题
我之前部署Laravel应用到生产环境时也碰到过一模一样的问题——本地测试完全正常,一上生产就报CSRF过期,咱们一步步来排查和解决:
1. 优先检查Session配置(最常见原因)
Laravel的CSRF Token验证完全依赖Session,生产环境的Session配置很容易出问题:
- Session驱动与存储权限:本地用
file驱动没问题,但生产环境如果也是file,要确保storage/framework/sessions目录的权限正确(给web服务器用户读写权限,比如执行chown -R www-data:www-data storage/)。更推荐生产用redis或database驱动,避免单服务器存储的局限,修改.env配置:SESSION_DRIVER=redis SESSION_LIFETIME=120 # 设置合理的过期时间,默认120分钟,别设太短 - Session域名与URL匹配:检查
.env里的APP_URL是否和生产环境域名一致(HTTPS站点必须带https://),同时config/session.php里的domain配置要匹配主域名,比如子域名环境设为.yourdomain.com,确保Session能正常跨域共享。
2. 确保CSRF Token正确传递
- 表单提交场景:确认表单里正确使用了Blade的
@csrf指令,生成的Token会随表单自动提交:<form method="POST" action="/submit-form"> @csrf <!-- 表单字段 --> </form> - AJAX请求场景:如果是AJAX提交,要在请求头里带上
X-CSRF-TOKEN,可以先在页面头部添加meta标签:
再在JS里全局配置请求头:<meta name="csrf-token" content="{{ csrf_token() }}">$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } });
3. 避免生产环境页面缓存导致Token过期
生产环境的CDN、Nginx缓存或者浏览器缓存可能把带有CSRF Token的页面静态化,导致用户提交时用的是过期Token:
- 在渲染表单的控制器方法里添加缓存控制头,禁止页面缓存:
public function showForm() { return response()->view('forms.your-form') ->header('Cache-Control', 'no-cache, no-store, must-revalidate') ->header('Pragma', 'no-cache') ->header('Expires', '0'); } - 如果用了Nginx,也可以在站点配置里给表单页面单独添加缓存禁止规则。
4. 负载均衡环境的Session共享问题
如果生产用了多台服务器做负载均衡,必须确保所有服务器共享同一个Session存储(比如Redis或数据库),不然用户请求分发到不同服务器时,Session不互通,就会出现Token验证失败的情况。
5. 关于VerifyCsrfToken的Except数组
不建议随便把业务路由加入$except数组(除非是第三方Webhook这类不需要CSRF验证的场景),如果确实要排除,要确保路由路径完全匹配,比如你的表单提交路由是/admin/form-submit,就准确添加:
protected $except = [ 'admin/form-submit', ];
先从Session配置和Token传递这两点入手排查,本地正常的情况下,90%的概率是生产环境的环境配置差异导致的问题。
内容的提问来源于stack exchange,提问作者josedan10
相关产品推荐
相关产品推荐

