codeigniter 3 csrf禁止jquery ajax调用

时间:2017-08-05 16:06:03

标签: jquery ajax codeigniter

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的情况下修复它,如果我想将它用于网站中的其他元素,我宁愿不这样做?

4 个答案:

答案 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...
                            }
 });