windows 10,codeigniter 3,jquery 3
我正在测试ajax函数,我正在使用$ .post函数将数据加载到div中并发送到读取文件并发送回内容的控制器方法(我知道还有其他方法可以做但是这是一个测试)。 ajax调用看起来像这样
var btn = 'a[href="click-help"]'
$(btn).click(function(){
$.post(
base_url+'site/cal_help',
function(data){
$('.cal-help').html(data);
});
}
return false;
});
您可以看到点击按钮不是表单而是链接。如果我将csrf设置为false,则此工作正常,但如果启用了csrf,控制台会将调用显示为禁止。在线研究后,我尝试传递数据如下:
{
'<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>'
},
但它没有帮助。如何在不将csrf设置为false的情况下修复它,如果我想将它用于网站中的其他元素,我宁愿不这样做?
答案 0 :(得分:1)
在所有ajax请求中启用了CSRF保护的项目,我确实遇到了类似的问题。然后我发现它发生是因为csrf令牌在每个请求上重新生成将导致禁止错误,因为令牌不匹配。因此,解决方案是在每个请求上关闭CSRF令牌生成。您可以通过在config.php文件中设置此选项来完成此操作。
$config['csrf_regenerate'] = FALSE;
请注意,当我检查laravel的CSRF令牌时,它并未在所有请求中更改。因此,将csrf重新生成选项更改为false不会导致任何重大安全问题。如果以上方法不适合您,请在下面评论。
答案 1 :(得分:1)
我还在努力解决这个问题,并且我发现了一些更有趣的事情:
虽然您可以像这样使用Codeigniter Security类:
<?php echo $this->security->get_csrf_token_name(); ?>
<?php echo $this->security->get_csrf_hash(); ?>
在视图中并且这些函数有效,您也应该能够在脚本文件中使用它们,例如
var hash = '<?php echo $this->security->get_csrf_hash();?>';
console.log(hash);
这似乎适用于视图中的脚本标记,但如果在单独的script.js文件中,控制台只显示打印出来的代码。为什么会发生这种情况?
但是我挖掘了js字符串方法并发现以下方法可以检索哈希:
//get all cookies
var x = document.cookie;
//search for the csrf cookie name
var posname = x.search('csrf_cookie_name');
//slice out hash itself which is always 32 characters long and these numbers work
var hash = x.slice(posname+17,posname+49);
console.log(hash);
建立了一个等于哈希的变量后,您可以将以下数据添加到您的ajax调用中:
{
'csrf_test_name' : hash
},
我把所有内容放在&#39;点击&#39;功能,以便找到最新版本的cookie。所以我最终得到这样的东西:
var btn = '.btn-cal-help a';
$(btn).click(function(){
var x = document.cookie;
var posname = x.search('csrf_cookie_name');
var hash = x.slice(posname+17,posname+49);
//console.log(hash);
$.post(
base_url + 'site/cal_help',
{
'csrf_test_name' : hash
},
function(data){
$('.cal-help').html(data);
});
}
return false;
});
现在虽然我有&#c;也设置为TRUE。
答案 2 :(得分:0)
就这样。获取每个新请求的令牌和哈希并将其附加到您的帖子数据
在您的模型/控制器中放置这样的东西
$reponse = array(
'csrfName' => $this->security->get_csrf_token_name(),
'csrfHash' => $this->security->get_csrf_hash()
);
// Your logic
return $this->output
->set_content_type('application/json')
->set_status_header(200)
->set_output(json_encode(array("regen" => $reponse, "response" => array("status" => $status, "message" => $message))));
在javascript部分
var csrfName = '<?php echo $this->security->get_csrf_token_name(); ?>',
csrfHash = '<?php echo $this->security->get_csrf_hash(); ?>';
$.ajax({
url: __URL__,
type: "POST",
data: $form.serialize() + "&" + csrfName + "=" + csrfHash,
mimeType: "multipart/form-data",
contentType: false,
dataType: 'json',
cache: false,
processData: false,
success: function (data) {
csrfName = data.regen.csrfName;
csrfHash = data.regen.csrfHash;
if (data.response.status) // if STATUS = TRUE
{
if (data.response.message === "__WHATEVER__") {
// and message === "__WHATEVER__"
}
}
}
});
答案 3 :(得分:0)
将$config['csrf_protection'] = TRUE;
设置为 FALSE 并不是解决该问题的好方法。在 AJAX 请求期间发生的事情是,当请求发送到您的控制器时,它将在提交期间验证有效令牌。因此,您需要传递令牌名称和哈希令牌,以便将其读取为有效。
这是...
$.ajax({
url: url,
type: "post",
data: {'<?php echo $this->security->get_csrf_token_name(); ?>':'<?php echo $this->security->get_csrf_hash(); ?>'},
success:function() {
//do stuff here...
}
});