简体   繁体   中英

Laravel 4, Token mismatch exception in filters.php using CSRF

I have a problem since 1 week more or less and when I leave open the page of my application but without using it for maybe 4 or 5 hours and return to make a request (a click on a button to load something or things like that) everytime in the console display this:

{
"error":{
    "type":"Illuminate\\Session\\TokenMismatchException",
    "message":"",
    "file":"C:\\xampp182\\htdocs\\mysite\\app\\filters.php",
    "line":97
    }
}

I'm using CSRF protección in my POST request passing for the ajax request this configuration

$.ajax({
        url: '/path/to/file',
        type: 'default GET (Other values: POST)',
        dataType: 'default: Intelligent Guess (Other values: xml, json, script, or html)',
        data: {param1: 'value1'},
        headers: {
            'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
        },
    })
    .done(function() {
        console.log("success");
    })
    .fail(function() {
        console.log("error");
    })
    .always(function() {
        console.log("complete");
    });

This is my filters.php

/*
|--------------------------------------------------------------------------
| CSRF Protection Filter
|--------------------------------------------------------------------------
|
| The CSRF filter is responsible for protecting your application against
| cross-site request forgery attacks. If this special token in a user
| session does not match the one given in this request, we'll bail.
|
*/

Route::filter('csrf', function($route, $request)
{
    if (strtoupper($request->getMethod()) === 'GET')
    {
        return; // get requests are not CSRF protected
    }

    $token = Request::ajax() ? Request::header('x-csrf-token') : Input::get('_token');

    if (Session::token() != $token)
    {
        throw new Illuminate\Session\TokenMismatchException; //Line 97
    }
});

Edit

I see the problem, the Session::token() and $token are different but is there a way to regenerate or put the both tokens with the same value?

This is how CSRF protection works. After session lifetime it generates new token. No one normally will fill in the form for 4-5 hours. If you do it just for testing on your localhost you may change lifetime in app/config/session to higher value and it should work.

Otherwise you may probably change:

throw new Illuminate\Session\TokenMismatchException; //Line 97

into something like that

 return Redirect:back()->withInput(Input::except('token'))->with('_token',Session::token());

I had this problem on login also. From time to time this exception occurred so I stop and tried to reproduce it. I succeed by doing this:

First I load the login page.

Then I deleted the cookies.

Then, without reloading the login page, I entered username and password and tried to login.

Because session was deleted (when I deleted the cookies), it was normal that this code was not going to pass and it will throw the TokenMismatchException.

Route::filter('csrf', function() {
    if ( Session::getToken() != Input::get('_token')) {
        throw new Illuminate\Session\TokenMismatchException;
    }
});

So, what I've done to solve my problem was to add a redirect to login page with a message to inform the user that the session might expired.

Route::filter('csrf', function() {
    if ( Session::getToken() != Input::get('_token')) {
        return Redirect::to('/admin/login')->with('warning', 'Your session has expired. Please try logging in again.');
    }
});

Thus, after page reloading, a new session is created and the problem is solved.

Simply place the code below into your filters:

if (Session::token() !== $token)
{
    return Redirect::back()->withInput(Input::except('_token'));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM