Laravel 5.5 Ajax请求多次尝试后频繁出现419错误的排查与解决
兄弟,你猜的完全没错!这个问题确实是CSRF令牌/会话过期搞的鬼,而且大概率是本地Windows环境下Laravel的会话配置在搞事情——线上服务器一般用更稳定的会话存储(比如Redis、数据库),而本地默认用文件存储,加上Windows文件系统的特性,会话过期逻辑触发得比线上频繁多了。
下面给你几个不用在verifyCsrfToken加例外的解决方案,按优先级排序:
1. 动态获取最新的CSRF令牌(最直接的临时解决)
你现在的代码里用的是页面加载时生成的静态{{csrf_token()}},当页面停留时间超过会话有效期,这个令牌就失效了。改成每次请求前从页面元标签动态获取最新令牌,就能避免这个问题:
修改你的Ajax请求代码:
$.ajax({ url: "/getCompare", type: "POST", cache: false, // 注意你之前写的是`cash`,这里是笔误,得改成`cache` data: { id: id, _token: $('meta[name="csrf-token"]').attr('content') }, success: function(response) { $("#compare_products").html(response); } });
如果你的全局$.ajaxSetup配置是固定令牌的,也改成动态获取:
$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } });
这样每次发起请求都会拿当前页面的有效令牌,不会因为页面停留久了导致令牌过期。
2. 调整本地会话过期时间
打开config/session.php,找到会话生命周期的配置,把默认的有效期改长一点(默认是120分钟,可能你本地被改成了3分钟?):
// 把会话有效期改成8小时(480分钟) 'lifetime' => 480, // 关闭浏览器后不立即过期会话 'expire_on_close' => false,
修改后记得清除配置缓存(本地开发可以跳过,但执行一下更稳妥):
php artisan config:clear
3. 更换本地会话驱动(根治本地环境问题)
本地默认用file驱动存储会话,Windows下的文件锁、读写延迟可能导致会话文件提前失效。换成database驱动会稳定很多:
- 打开
.env文件,修改会话驱动:
SESSION_DRIVER=database
- 生成会话表的迁移文件:
php artisan session:table
- 执行迁移创建会话表:
php artisan migrate
之后本地会话就会存在数据库里,不会再因为Windows文件系统的问题提前过期了。
4. 检查会话Cookie有效期
确保会话Cookie的有效期和会话生命周期一致,打开config/session.php:
// 设置Cookie有效期和会话生命周期相同 'cookie_lifetime' => 480,
补充说明
你提到上线后问题自动消失,完全符合预期——线上服务器通常会用Redis、Memcached或者数据库这类更可靠的会话存储方案,而且服务器的文件系统不会像Windows本地那样存在会话文件的读写异常,所以会话过期逻辑会正常执行,不会出现提前失效的情况。
内容的提问来源于stack exchange,提问作者Salar Bahador

