我认为@UX Labs 的回答具有误导性。
然后@jfadich 的评论似乎完全不正确。
对于 2017 年 5 月的 Laravel 5.4,我这样解决了这个问题:
这是一个有效的答案
在web.php:
Route::post('keep-token-alive', function() {
return 'Token must have been valid, and the session expiration has been extended.'; //https://stackoverflow.com/q/31449434/470749
});
在你看来的javascript中:
$(document).ready(function () {
setInterval(keepTokenAlive, 1000 * 60 * 15); // every 15 mins
function keepTokenAlive() {
$.ajax({
url: '/keep-token-alive', //https://stackoverflow.com/q/31449434/470749
method: 'post',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}).then(function (result) {
console.log(new Date() + ' ' + result + ' ' + $('meta[name="csrf-token"]').attr('content'));
});
}
});
请注意,您必须不在VerifyCsrfToken.php 的排除项中列出'keep-token-alive'。正如@ITDesigns.eu 在评论中所暗示的那样,这条路线重要的是要验证当前存在一个有效的令牌并且它只需要延长其到期时间。
为什么这种方法可以解决我的问题
我的 Laravel 网站允许用户观看视频(一小时长),它使用 ajax 每分钟发布他们的进度。
但许多用户加载页面后,直到数小时后才开始播放视频。
我不知道为什么他们会在观看之前将浏览器选项卡打开这么久,但他们确实如此。
然后我的日志中会出现大量的 TokenMismatch 异常(并且会错过它们的进度数据)。
在 session.php 中,我将 'lifetime' 从 120 分钟更改为 360 分钟,但这仍然不够。而且我不想让它超过6小时。所以我需要启用这一页以通过ajax频繁扩展会话。
如何测试它并了解令牌的工作原理:
在web.php:
Route::post('refresh-csrf', function() {//Note: as I mentioned in my answer, I think this approach from @UX Labs does not make sense, but I first wanted to design a test view that used buttons to ping different URLs to understand how tokens work. The "return csrf_token();" does not even seem to get used.
return csrf_token();
});
Route::post('test-csrf', function() {
return 'Token must have been valid.';
});
在你看来的javascript中:
<button id="tryPost">Try posting to db</button>
<button id="getNewToken">Get new token</button>
(function () {
var $ = require("jquery");
$(document).ready(function () {
$('body').prepend('<div>' + new Date() + ' Current token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>');
$('#getNewToken').click(function () {
$.ajax({
url: '/refresh-csrf',
method: 'post',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}).then(function (d) {
$('meta[name="csrf-token"]').attr('content', d);
$('body').prepend('<div>' + new Date() + ' Refreshed token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>');
});
});
$('#tryPost').click(function () {
$.ajax({
url: '/test-csrf',
method: 'post',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
}).then(function (d) {
$('body').prepend('<div>' + new Date() + ' Result of test: ' + d + '</div>');
});
});
});
})();
在session.php 中,暂时将'lifetime' 更改为非常短的内容以进行测试。
然后玩。
这就是我如何了解 Laravel 令牌的工作原理以及我们真正需要如何频繁地成功 POST 到受 CSRF 保护的路由以使令牌继续有效。