问题
I can't understand why I cannot do more than one request without refreshing page.
Any request is working fine, but If I need to execute another request (don't mind if it's the same or not)... I can't! I need to refresh the page to do a new request, otherwise, I'll get error 403.
All the code is working, just, any request is finishing with refreshing the page. I don't like that because I consider it's not professional.
What do I need to change in codeigniter to allow more than one request without refreshing the page?
update from comment: I use csrf protection and I don't want to disable it.
@Vickel this is one of the requests (all of them is almost the same, just url and data)... there's no form.
function set_tracking(order_id)
{
$.ajax({
type: "POST",
data: {
order_id: order_id
},
url: trackingURL,
beforeSend: function() {
$('.lds-default').removeClass('hidden');
},
success: function (response) {
console.log(response);
if(response.error)
{
show_form_errors(lang['productions_error_not_set_tracking']);
} else {
$('#set_tracking .modal-title').html(lang['productions_set_tracking_title']);
$('#set_tracking').modal('show');
$('#set_tracking #order_id').val(order_id);
}
},
error: function (event) {
if (event.status !== 401) {
show_form_errors(lang['companies_error_deleting_segment']);
}
},
complete: function() {
$('#confirm_message').modal('hide');
$('.lds-default').addClass('hidden');
}
});
}
回答1:
You're encountering an expired CSRF token. There's multiple ways around this (each with different complexity and security levels)
1.- Disable CSRF altogether (not recommended unless all your forms live within a secure area where everyone is logged in and there's no way to get a cross-domain request, which is unlikely.
2.- Define exceptions for the CSRF functionality. In application/config/config.php
you'll find an array called $config['csrf_exclude_uris']
where you can add all the controller/method pairs for which you wish the CSRF checks to not be enforced
3.- Disable CSRF regeneration. In application/config/config.php
you could set $config['csrf_regenerate']
to false
. This will prevent the CSRF token to be regenerated after each request, which would allow you to make more than one submission without being blocked by the CSRF check
4.- Manually get a regenerated token after the first submission and pass it along with the second submission. This is the most secure way to address your issue, but the most complex. You can read about this in depth in the Codeigniter's Security Class documentation here
回答2:
in order to manually regenerate the CSRF token you can do the following:
- create an hidden input field in your view, which stores your csrf token
- in your controler, you create a new token and send it back with your ajax response
- in your ajax success function, you update your hidden input field
now you are ready for sending a new request
view:
<?php
$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash()
);
?>
<input type="hidden" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />
javascript:
tn='<?php echo $this->security->get_csrf_token_name(); ?>';
th=$('input[name="'+tn+'"]').val();
csfrData={tn:th};
$.ajax({
type: "POST",
dataType:json,
data: {
order_id: order_id,
csrf:csfrData // send current token
},
//etc...
success: function (response) {
// update hidden input field with new token
$('input[name="'+response.csrf.csrf_name+'"]').val(response.csrf.csrf_hash)
// etc
}
})
controller:
function your_tracking_url(){
$data['yourdata']=array() // whatever you return
$data['csrf']=$this->get_csrf();
echo json_encode($data);
}
function get_csrf(){
// creating a new token
$csrf=array('csrf_name'=>$this->security->get_csrf_token_name(),'csrf_hash'=>$this->security->get_csrf_hash());
return $csrf;
}
you might need to adapt this a little bit, but it shows the concept how manual csrf token regeneration works
来源:https://stackoverflow.com/questions/62262470/avoid-error-403-in-codeigniter-on-a-second-post-request