Handling expired token in Laravel

后端 未结 13 2786
情话喂你
情话喂你 2020-11-29 00:30

What is the best way to handle expired tokens in laravel 5.

I mean I have a page and it has some links which perform ajax requests. They work fine when the page is

13条回答
  •  情话喂你
    2020-11-29 01:10

    I think the answer by @UX Labs is misleading. And then the comment from @jfadich seems completely incorrect.

    For Laravel 5.4 in May 2017, I solved the problem this way:

    Here Is an Answer That Works

    In 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
    });
    

    In javascript in your view:

    $(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'));
            });
        }
    
    });
    

    Note that you must not list 'keep-token-alive' in the exclusions within VerifyCsrfToken.php. As @ITDesigns.eu implied in a comment, it's important for this route to verify that there is a valid token currently and that it just needs to have its expiration extended.

    Why this approach solves my problem

    My Laravel site allows users to watch a video (an hour long), and it uses ajax to post their progress every minute.

    But many users load the page and then don't start the video until many hours later.

    I don't know why they leave their browser tab open so long before watching, but they do.

    And then I'd get a ton of TokenMismatch exceptions in my logs (and would miss out on the data of their progress).

    In session.php, I changed 'lifetime' from 120 to 360 minutes, but that still wasn't enough. And I didn't want to make it longer than 6 hours. So I needed to enable this one page to frequently extend the session via ajax.

    How you can test it and get a sense for how the tokens work:

    In 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.';
    });
    

    In javascript in your view:

    
    
    
    (function () {
        var $ = require("jquery");
    
        $(document).ready(function () {
            $('body').prepend('
    ' + new Date() + ' Current token is: ' + $('meta[name="csrf-token"]').attr('content') + '
    '); $('#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('
    ' + new Date() + ' Refreshed token is: ' + $('meta[name="csrf-token"]').attr('content') + '
    '); }); }); $('#tryPost').click(function () { $.ajax({ url: '/test-csrf', method: 'post', headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }).then(function (d) { $('body').prepend('
    ' + new Date() + ' Result of test: ' + d + '
    '); }); }); }); })();

    In session.php, temporarily change 'lifetime' to something very short for testing purposes.

    Then play around.

    This is how I learned how the Laravel token works and how we really just need to successfully POST to a CSRF-protected route frequently so that the token continues to be valid.

提交回复
热议问题