Laravel 5 で期限切れのトークンを処理する最適な方法は何ですか。
つまり、ページがあり、そこには Ajax リクエストを実行するリンクがいくつかあります。ページが読み込まれるとそれらは正常に動作しますが、しばらく待つと TOKEN MISMATCH エラーが発生します。
再び動作させるには、ページを更新する必要があります。しかし、ページを更新したくありません。トークンを更新する方法、または修正するための他の回避策が必要です。
私の言いたいことが伝われば幸いです。
ベストアンサー1
@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'));
});
}
});
注意してくださいない'keep-token-alive'
内の除外リストVerifyCsrfToken.php
。@ITDesigns.euがコメントで示唆したように、このルートでは有効なトークンがあることを確認することが重要です現在そして、有効期限を延長する必要があるだけだ。
このアプローチが私の問題を解決する理由
私の Laravel サイトでは、ユーザーがビデオ (1 時間) を視聴できるようにしており、Ajax を使用して 1 分ごとに進行状況を投稿します。
しかし、多くのユーザーはページを読み込んでから数時間経ってから初めてビデオを視聴します。
なぜ視聴前にブラウザのタブを長時間開いたままにするのかはわかりませんが、実際にそうしています。
そして、ログに大量の TokenMismatch 例外が記録されてしまいます (そして、その進行状況のデータを見逃してしまいます)。
ではsession.php
、120 分から 360 分に変更しましたが'lifetime'
、それでも十分ではありませんでした。また、6 時間以上にはしたくありませんでした。そのため、この 1 つのページで 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 トークンがどのように機能するか、そしてトークンが引き続き有効であるようにするには、CSRF で保護されたルートに頻繁に POST を正常に実行する必要があることを学びました。