我通过jquery字符串发送Cross站点伪造令牌,但在下一页我生成一个新令牌然后他们的令牌将永远不会匹配

Okay, so I am storing their tokes in a session:

Session::get('token', 'randomtokenstringhere');

On each form, whether it's successful or not I generate a new token, and update their session token, now say for example user 1 is on a update profile page, and I serialize a form, with a token on page load echo the token variable) and they submit the form, which runs an ajax, and either completes or there's an error, my system generate a new token, but now on the edit profile page, they're still using the old token, so now their tokens will never match.

How can I fix this for extra security?

Here's an example of my ajax:

<!-- accept, reject, add and cancel friend requests -->
$('.add_friend').click(function(event) { // bind function to submit event of form
    event.preventDefault();
    $.ajax({
        url: $(this).attr('href'),
        success: function(responseText) {
            if($(event.target).text() == 'Add as friend'){
                $(event.target).attr("href", "<?php echo Config::get('URL'); ?>friends/cancel_request/" + $(event.target).attr('id') + "/<?php echo System::escape(Session::get('token')); ?>");
                $(event.target).text('Cancel Request');
                $(event.target).removeClass("add_friend btn btn-success").addClass("cancel_request btn btn-info");                  
            }else{
                $(event.target).attr("href", "<?php echo Config::get('URL'); ?>friends/addfriend/" + $(event.target).attr('id') + "/<?php echo System::escape(Session::get('token'));?>");
                $(event.target).text('Add as friend');  
                $(event.target).removeClass("cancel_request btn btn-info").addClass("add_friend btn btn-success");                  
            }
        }
    });
    return false;
});
<!-- End Like a status -->

which ofcourse run the following link:

<a class="add_friend btn btn-success" id="<?php echo System::escape($likes->timeline_likes_id); ?>" href="<?php echo Config::get('URL'); ?>friends/addfriend/<?php echo System::escape($likes->user_id).'/'.System::escape(Session::get('token')); ?>"><?php echo System::translate("Add as friend"); ?></a>

Their token is: System::escape(Session::get('token')); ?> which will only load on page refresh which defauts my reason for using ajax

To update the value in your javascript, you'll want to modify your js somewhat.

Something like this should get you on the right track

<!-- accept, reject, add and cancel friend requests -->
$('.add_friend').click(function(event) { // bind function to submit event of form
    event.preventDefault();
    var token = <?php echo System::escape(Session::get('token'));?>;
    $.ajax({
        url: $(this).attr('href'),
        success: function(responseText) {
            if($(event.target).text() == 'Add as friend'){
                $(event.target).attr("href", "<?php echo Config::get('URL'); ?>friends/cancel_request/" + $(event.target).attr('id') + "/" + token);
                $(event.target).text('Cancel Request');
                $(event.target).removeClass("add_friend btn btn-success").addClass("cancel_request btn btn-info");                  
            }else{
                $(event.target).attr("href", "<?php echo Config::get('URL'); ?>friends/addfriend/" + $(event.target).attr('id') + "/" + token);
                $(event.target).text('Add as friend');  
                $(event.target).removeClass("cancel_request btn btn-info").addClass("add_friend btn btn-success");                  
            }
            token = responseText;
        }
    });
    return false;
});
<!-- End Like a status -->

Now all you have to do is modify the form handler at $(this).attr('href') to echo the new session token. The JS will set the token value to the new token and use that in subsequent requests.

What this is doing is placing your token in a variable that can be updated after each call so that you are able to change it after a successful request.

You need to implement nonces! From the wikipedia article:

A nonce is an arbitrary number used only once in a cryptographic communication, in the spirit of a nonce word. They are often random or pseudo-random numbers. Many nonces also include a timestamp to ensure exact timeliness ... To ensure that a nonce is used only once, it should be time-variant (including a suitably fine-grained timestamp in its value), or generated with enough random bits to ensure a probabilistically insignificant chance of repeating a previously generated value. Some authors define pseudorandomness (or unpredictability) as a requirement for a nonce.

Anyway, any pratical implimentation of this will require a minimum of 2 functions. The first will be something like createNonce() and the second will be something like verifyNonce(). If you're looking for a library that will do this for you, I've used OpenID in the past.

There are a whole bunch of valid ways to do this and it is fairly simple to write your own implementation. The basic concept is to create a string with data you can replicate. Then hash that data and put it in a field in your form. Then when you get the form data, you can recreate your hash and compare it to the hash that your form sent (similar to how you might verify a password). You need to make sure that your hash contains data that regularly changes (e.g. microtime()) so that your nonces are unique. With systems where users log in, I often use something from that user (e.g. a substring of their password hash) so that every user gets a unique nonce even if they are both generated in the same microsecond.