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();