javascript - Many AJAX requests at once with CSRF protection - Stack Overflow

Hi everybody.My web application is based on asynchronous requests. Timer widget is working and updating

Hi everybody.

My web application is based on asynchronous requests. Timer widget is working and updating it's status every second by AJAX (yes, it is necessary).

I am sending with each AJAX my CSRF tokens:

project_data.append(csrf_name_key,csrf_name_value);
project_data.append(csrf_value_key,csrf_value_value);

And in response I am updating that global variables:

function setCSRF(response) {
    csrf_name_key = response.nameKey;
    csrf_name_value = response.name;
    csrf_value_key = response.valueKey;
    csrf_value_value = response.value;      
}

Everything is generally fine. But if I will do another AJAX for example when I change task in todo list to "done" it sometimes ending with error because I am sending AJAX before I am getting new tokens from previous request.

I really don't know how to do solve that problem. First idea was that I will make "like stack array" with 5 different tokens but one https request = one pair of tokens and I can't generate it.

Maybe some type of queue of ajax requests, but what with doing them in a right time - I don't know.

My actual pseudo-solution is "if failed try again max 10 times":

if(e.target.response=="Failed CSRF check!") {
    if(failedAjax<10) checkForSurvey();
    failedAjax++;
    return;
}

It is generally working, but errors are appears in a console and it is very dirty solution.

I am using Slim 3 microframework with CSRF extension. Really please for help with that interesting problem.

I will be very thankful,

Arthur

Hi everybody.

My web application is based on asynchronous requests. Timer widget is working and updating it's status every second by AJAX (yes, it is necessary).

I am sending with each AJAX my CSRF tokens:

project_data.append(csrf_name_key,csrf_name_value);
project_data.append(csrf_value_key,csrf_value_value);

And in response I am updating that global variables:

function setCSRF(response) {
    csrf_name_key = response.nameKey;
    csrf_name_value = response.name;
    csrf_value_key = response.valueKey;
    csrf_value_value = response.value;      
}

Everything is generally fine. But if I will do another AJAX for example when I change task in todo list to "done" it sometimes ending with error because I am sending AJAX before I am getting new tokens from previous request.

I really don't know how to do solve that problem. First idea was that I will make "like stack array" with 5 different tokens but one https request = one pair of tokens and I can't generate it.

Maybe some type of queue of ajax requests, but what with doing them in a right time - I don't know.

My actual pseudo-solution is "if failed try again max 10 times":

if(e.target.response=="Failed CSRF check!") {
    if(failedAjax<10) checkForSurvey();
    failedAjax++;
    return;
}

It is generally working, but errors are appears in a console and it is very dirty solution.

I am using Slim 3 microframework with CSRF extension. Really please for help with that interesting problem.

I will be very thankful,

Arthur

Share Improve this question asked Apr 6, 2017 at 10:43 ArtimalArtimal 6618 silver badges26 bronze badges 14
  • I would give each action (timer, update todo, etc.) its own csrf token. – jeroen Commented Apr 6, 2017 at 10:47
  • But for generate token you need to make http request. For make that request you need to pass actual tokes or wait - maybe I will off CSRF protection for "token generator" route? Is this a save solution? – Artimal Commented Apr 6, 2017 at 10:49
  • Can't you send the initial tokens on page load? – jeroen Commented Apr 6, 2017 at 10:50
  • 1 The approach may you take as you can create an CSRF token array per session base and then check a ining token is present in the array or not. If yes then you can validate the request else not, and fire another ajax at every minute which will delete the old csrf token from the array. But as I don't know the slim framework, so I can't suggest how can you hack slim to implement this. I hope this may serve your purpose – Abhisek Malakar Commented Apr 6, 2017 at 10:57
  • 1 Then you should use the CSRF Token to request a new array of csrf tokens, as said by @AbhisekMalakar If you don't worry about performance you could make the ajax request wait untill a new CSRF tokens arrives. – Eaton Emmerich Commented Apr 6, 2017 at 11:19
 |  Show 9 more ments

2 Answers 2

Reset to default 4

There are some options for you:

  1. Use a stack of csrf-tokens inside you javascript code

  2. Use a csrf token which is can be used more than once (not so secure)

  3. Use a queue for the request

A stack for the tokens

The Slim-Csrf-middleware provides functionallity for you, to generate these tokens, you just need to get them to the clientside. You could do an api for getting 5 csrf tokens, this api would also consume on csrf-token.

Add an api and generate the tokens there.

$app->get('/foo', function ($request, $response, $args) {
    // check valid  csrf token

    $tokens = [];
    for ($i = 0; $i < 5; $i++) {
        $tokens[] = $this->csrf->generateToken();
    }

    return $response->withJson($tokens);
});

Now the csrf-token are valid through the whole user session.

Guard::generateToken() returns something like this:

array (size=2)
  'csrf_name' => string 'csrf58e669ff70da0' (length=17)
  'csrf_value' => string '52ac7689d3c6ea5d01889d711018f058' (length=32)

A multi-use csrf-token

For that, Slim-Csrf already provides functionallity with the token persistance mode. That can be enabled through the constructor or the Guard::setPersistentTokenMode(bool) method. In my example, I'm doing this with the method:

$container['csrf'] = function ($c) {
    $guard = new \Slim\Csrf\Guard;
    $guard->setPersistentTokenMode(true);
    return $guard;
};

Here the PhpDoc from the persistanceTokenMode-attribute

/**
 * Determines whether or not we should persist the token throughout the duration of the user's session.
 *
 * For security, Slim-Csrf will *always* reset the token if there is a validation error.
 * @var bool True to use the same token throughout the session (unless there is a validation error),
 * false to get a new token with each request.
 */

A queue for the ajax requests.

Add a queue for the request, that could be delay the execution of your request but there will always be a valid csrf token.

This should be seen as pseudocode as I havn't tested this yet.

var requestQueue = [];
var isInRequest = false;

var csrfKey = ''; // should be set on page load, to have a valid token at the start
var csrfValue = '';

function newRequest(onSuccessCallback, data) { // add all parameters you need
    // add request to the queue
    requestQueue.push(function() {
        isInRequest = true;
        // add to csrf stuff to data
        $.ajax({
            data: xxx
            url: "serverscript.xxx",
            success: function(data) {
                // update csrfKey & csrfValue
                isInRequest = false;
                tryExecuteNextRequest(); // try execute next request
                onSuccessCallback(data); // proceed received data
            }
        }});
    );
    tryExecuteNextRequest();
}

function tryExecuteNextRequest() {
    if(!isInRequest && requestQueue.length != 0) { // currently no request running &
        var nextRequest = requestQueue.shift();
        nextRequest(); // execute next request
    }
}

Generally, you can simply eliminate CSRF by not accepting cookies for authentication.

You can save the authentication token in the localStorage and send it as an header with each request.

This way you'll never need to worry about CSRF and its tokens.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745609569a4635869.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信