简体   繁体   中英

Using CSRF Protection Service with Ajax in Phalcon

I have trouble with CSRF protection component in Phalcon with Ajax.

html form

<form id="signup-form" onSubmit="onSignUpSubmit(); return false;">
    <input id="username" type="text" placeholder="Username" />
    <input id="password" type="password" placeholder="Password" />
    <input id="email" type="text" placeholder="Email" />
    <input id="signup-csrf-token" name="{{ security.getTokenKey() }}" val="{{ security.getToken() }}" type="hidden" />
    <button class="btn btn-primary btn-block" type="submit">Sign Up</button>
</form> <!-- #signup-form -->

Ajax code

var username    = $('#username', '#signup-form').val(),
    password    = $('#password', '#signup-form').val(),
    email       = $('#email', '#signup-form').val(),
    csrfKey     = $('#signup-csrf-token').attr('name'),
    csrfValue   = $('#signup-csrf-token').attr('val');

    var postData = {
        'username': username,
        'password': password,
        'email': email
    };
    postData[csrfKey] = csrfValue;

    $.ajax({
        type: 'POST',
        url: '{{ url('/accounts/signup.action') }}',
        data: postData,
        dataType: 'JSON',
        success: function(result){
            console.log(result);
        }
    });

When send Ajax request for the first time, the $this->security->checkToken() function in Controller returns true. But for the second time and later, the function returns false.

I think the csrfToken changes for each HTTP request caused this problem. But how to solve it?

Can anyone help me?

You will need to return the new CSRF token in your AJAX success response. Then update your form field with the new token.

accounts/signup.action

return json_encode((object) array(
    'output' => $original_output,
    'csrf' => (object) array('name' => $csrf_name, 'value' => $csrf_token)
));

Javascript

$.ajax({
    type: 'POST',
    url: '{{ url('/accounts/signup.action') }}',
    data: postData,
    dataType: 'JSON',
    success: function(result){
        $('input#signup-csrf-token')
            .attr('name', result.csrf.name)
            .val(result.csrf.value);
        console.log(result.output);
    }
});

You should also change

$('#signup-csrf-token').attr('val');

to

$('#signup-csrf-token').val();

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