php Codeigniter CSRF仅对一次ajax请求有效
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38502548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Codeigniter CSRF valid for only one time ajax request
提问by romio
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
我想在 jQuery 的更改事件上在服务器上上传图像,但使用 codeigniter csrf 我只能上传图像一次。如何使用ajax为多个请求上传图像。设置时请记住
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
然后我可以发送多个请求 jQuery onchange 事件,但是当 csrf_protection 为 false 时,我认为 csrf 没有优势。所以问题是如何在启用 csrf_protection 的情况下使用 ajax 发送多个请求。我的 jquery 代码如下
$("#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);
}
});
});
回答by Edu
In my opinion you should try to recreate your csrf token each request
我认为您应该尝试在每个请求中重新创建您的 csrf 令牌
Try this code example...
试试这个代码示例...
For the js funcion
对于 js 函数
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
注意:当有人要求您为问题发布更多数据时,不要将其作为评论或答案发布,最好编辑问题本身并添加内容
回答by Brian85
You can set this in config.php
你可以在 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
因此 csrf 保护在所有会话时间内都是有效的,它将解决您的问题。如果您设置,
$config['csrf_regenerate'] = true;
那么 CI 会在每个请求中生成新的 csrf 令牌,因此您的旧 csrf 令牌与新生成的 csrf 令牌不匹配
回答by Brian85
All you need to do is reload the CSRF token in your AJAX response. It is that simple!.
您需要做的就是在 AJAX 响应中重新加载 CSRF 令牌。就是这么简单!。
回答by Vishnu Bhadoriya
$config['csrf_regenerate'] = TRUE;
$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
保持自动生成为真它会更安全。在类似的情况下,当 csrf 在第一个请求中过期时。我已经实施的
$(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
在每个 ajax 响应中,我们都传递 csrf 数据,其中最新的 csrf 数据将替换为当前的
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
我在每个 ajax 请求中更新 csrf 令牌。如果您正在使用多选项卡环境,也不要选择此方法
回答by curiosity
Each time you make a request, the csrf_token
is being updated by CI. That's why the CSRFonly work once. So everytime we make a request we need to update the csrf_token too. I solve this problem by doing this.
每次您发出请求时,csrf_token
都会由CI更新。这就是CSRF只工作一次的原因。所以每次我们发出请求时,我们也需要更新 csrf_token。我通过这样做解决了这个问题。
Conroller: get the updated csrf using this code.
电脑板:获得更新的CSRF使用此代码。
public function update_csrf()
{
$data['csrf_hash'] = $this->security->get_csrf_hash();
echo json_encode($data);
}
AJAX: replace the old value of yourcsrfname="csrf_token_name"
AJAX:替换您的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'
重要!:使用
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.
所以现在每次你有一个成功的请求,它csrf_token
也会更新,你现在摆脱了 403 (Forbidden) error。
回答by Kevin TP
Maybe you can try using jquery cookie
也许你可以尝试使用 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
[csrf_protection] = TRUE;
回答by mohammad aghandeh
add this at a js file which is loaded every page (I put this at the end of jquery.js )
将此添加到每个页面加载的 js 文件中(我将其放在 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)
(请注意,在每个 ajax 请求中,您不能发送空数据)
"csrf_cookie_name" at top defined in config.php
在 config.php 中定义的顶部的“csrf_cookie_name”
$config['csrf_cookie_name'] = 'csrf_cookie_name';
回答by Md Suzon Mia
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
设置 jquery post 方法后,如下所示
// 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.
最重要的是,每个请求的代码都会重新创建您的 csrf 令牌。
回答by Mike
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.
Array 可以包含您希望禁用 csrf 保护的所有列入白名单的控制器/方法。
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
有关更多信息,请访问Codeigniter 文档 - 安全类