I want to upload image on the server on change event of jQuery but using codeigniter csrf I am able to upload image only one time. How can I upload images using ajax for mul
Each time you make a request, the csrf_token
is being updated by CI. That's why the CSRF only work once. So everytime we make a request we need to update the csrf_token too. I solve this problem by doing this.
Conroller: get the updated csrf using this code.
public function update_csrf()
{
$data['csrf_hash'] = $this->security->get_csrf_hash();
echo json_encode($data);
}
AJAX: replace the old value of your csrf name="csrf_token_name"
var jqXHR = $.ajax({
url: $(this).attr('action'),
type: 'POST',
data: $(this).serialize(),
dataType: 'json',
})
jqXHR.done(function(response) {
$('input[name=csrf_token_name]').val(response.csrf_hash); //update the csrf to the form
})
jqXHR.fail(function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
console.log(textStatus);
console.log(errorThrown);
});
Important!: use
dataType: 'json'
So now each time you have a successful request, the csrf_token
is updated too and you are now free from 403 (Forbidden) error.
You can set this in config.php
$config['csrf_regenerate'] = FALSE;
so the csrf protection is valid during all the session time it will solve your problem.
If you set
$config['csrf_regenerate'] = true;
then CI generate new csrf token every request so your old csrf token not match with new generated csrf token
Please try like my code. its working my application
your view file
$token_name = $this->security->get_csrf_token_name();
$token_hash = $this->security->get_csrf_hash();
<input type="text" id="search-text" name="parent_name" placeholder="Search" value="" >
<input type="hidden" id="csrf" name="<?php echo $token_name; ?>" value="<?php echo $token_hash; ?>" />
after set jquery post method like below
// Get Keyup
jQuery( "#search-text").keyup(function() {
// Get Data
var val = jQuery("#search-text").val();
var hashValue = jQuery('#csrf').val();
// Get jquery post for ajax task
jQuery.post(
'<?php echo $base_controler; ?>',
{val:val,'<?php echo $this->security->get_csrf_token_name(); ?>':hashValue},
function(data)
{
// Get return data to decode
var obj = jQuery.parseJSON(data);
// Get csrf new hash value
var new_hash = obj.csrfHash;
// Set csrf new hash value update
jQuery('#csrf').val(new_hash);
}
);
});
please set your controller like below
$reponse = array(
'csrfName' => $this->security->get_csrf_token_name(),
'csrfHash' => $this->security->get_csrf_hash()
);
echo json_encode($reponse);
above all code recreate your csrf token each request.
$config['csrf_regenerate'] = TRUE;
keep auto generate to true it will be more safer. In similar case when csrf is expired in first request. What i have implemented
$(document).ajaxComplete(function (event, xhr, settings) {
let response = xhr.responseText,
let obj = JSON.parse(response),
let csrfData = obj.csrf;
document.querySelector('input[name="' + csrfData.name + '"]').value = csrfData.hash;
}); //Also here you can update any other non input element
In every ajax response we are passing csrf data in which latest csrf data will be replaced with current one
Sample response from request
{
csrf : {
name : 'csrf_name',
hash : 'qw76sd7s6f78sdfs8dfs9df8cx9'
}
}
I update csrf token in every ajax request. Also don't choose this method if you are working with multi tab environment
All you need to do is reload the CSRF token in your AJAX response. It is that simple!.
Maybe you can try using jquery cookie
First you need to add this
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script>
then change your code to this
$("#avatar").change(function(){
var link = $("#avatar").val();
$.ajax({
url : "<?php echo base_url('main/test'); ?>",
type: 'post',
data: {csrf_test_name: $.cookie('csrf_cookie_name'),"id":"hello","link":link},
dataType : "JSON",
success : function(data)
{
alert(data);
}
});
Finally you can try to set your csrf_protection to true
[csrf_protection] = TRUE;