可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 multiple requests.Please keep in mind when I set this
config['csrf_protection'] = FALSE;
then I am able to send multiple request jQuery onchange event but when csrf_protection is going to be false then I think there is no advantage of csrf. so the question is how can I send multiple requests using ajax while csrf_protection is enable. My jquery code is following
$("#avatar").change(function(){
var link = $("#avatar").val();
$.ajax({
url : "<?php echo base_url('main/test'); ?>",
type: 'post',
data: {'<?php echo $this->security->get_csrf_token_name(); ?>':'<?php echo $this->security->get_csrf_hash(); ?>',"id":"hello","link":link},
success : function(data)
{
alert(data);
}
});
});
回答1:
In my opinion you should try to recreate your csrf token each request
Try this code example...
For the js funcion
var csrfName = '<?php echo $this->security->get_csrf_token_name(); ?>',
csrfHash = '<?php echo $this->security->get_csrf_hash(); ?>';
("#avatar").change(function(){
var link = $("#avatar").val();
var dataJson = { [csrfName]: csrfHash, id: "hello", link: link };
$.ajax({
url : "<?php echo base_url('main/test'); ?>",
type: 'post',
data: dataJson,
success : function(data)
{
csrfName = data.csrfName;
csrfHash = data.csrfHash;
alert(data.message);
}
});
});
and for the controller
public function test() {
$config['upload_path'] = './uploads/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = 500;
$config['max_width'] = 260;
$config['max_height'] = 260;
$reponse = array(
'csrfName' => $this->security->get_csrf_token_name(),
'csrfHash' => $this->security->get_csrf_hash()
)
$this->load->library('upload', $config);
if (!$this->upload->do_upload('link')) {
$reponse['message'] = "error";
}
else {
$data = array('upload_data' => $this->upload->data());
$image_name = $data['upload_data']['file_name'];
$reponse['message'] = $image_name;
}
echo json_encode($reponse);
}
Let me know and good luck
Note: When someone ask you for posting more data to the question, don't post it as a comment or answer, it's better to edit the question itself and adding the stuff
回答2:
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
回答3:
$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
回答4:
All you need to do is reload the CSRF token in your AJAX response. It is that simple!.
回答5:
add this at a js file which is loaded every page (I put this at the end of jquery.js )
$.ajaxSetup({
beforeSend:function(jqXHR, Obj){
var value = "; " + document.cookie;
var parts = value.split("; csrf_cookie_name=");
if(parts.length == 2)
Obj.data += '&csrf_token='+parts.pop().split(";").shift();
}
});
(notice that in every ajax request you can not have empty data to send)
"csrf_cookie_name" at top defined in config.php
$config['csrf_cookie_name'] = 'csrf_cookie_name';
回答6:
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.
回答7:
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.
回答8:
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;
回答9:
Edit the config:
$config['csrf_exclude_uris'] = ['controller/method'];
Array can include all whitelisted controllers/methods you want the csrf protection to be disabled for.
The array can also handle regular expressions such as:
$config['csrf_exclude_uris'] = array(
'api/record/[0-9]+',
'api/title/[a-z]+'
);
For more information visit Codeigniter Documentation - Security Class