Codeigniter ajax CSRF问题

IT技术 javascript ajax codeigniter token
2021-02-27 18:40:22

我制作了一个简单的自动加载功能,可以在您向下滚动网站时加载内容。但是,当我在 Codeigniter 中启用 CSRF 保护时,似乎存在一些问题。

我没有使用表单,所以我不知道如何在滚动时执行发布请求时将令牌从 A 发送到 B。

我的 JavaScript

if (location.href == baseurl) {
    $(window).scroll(function(){
        if ($(window).scrollTop() > $('body').height() / 2) {
            if(doScroll == 1) {
                $.post(baseurl + 'ajax/images',{'id' : ID}, function(data) {
                    $("#wrapper_content").append(data);
                    if(data == 'Det finnes ikke flere bilder i databasen, WTF!? Send inn forslag ASAP!') {
                        doScroll = 0;
                    }
                    ID++;
                });
            }
        }
    });
}

由于 Codeigniter 期望在所有 POST 请求上都有一个令牌,因此当启用 CSRF 时,我无法使其正常工作。有什么建议?

启用 CSRF 时出错

加载资源失败:服务器响应状态为 500(内部服务器错误)

如果我关闭 CSRF,一切正常......

6个回答

正如其他人所说 - 您必须使用 AJAX 请求参数发布 CSFR 令牌名称及其值。这是一个简单的解决方案,可以将它自动附加到每个 AJAX 请求。

这是我放在主视图中的内容,因此在加载其他 javascript 文件之前,此代码位于每个页面上:

   <script>
     var csfrData = {};
     csfrData['<?php echo $this->security->get_csrf_token_name(); ?>']
                       = '<?php echo $this->security->get_csrf_hash(); ?>';
   </script>
   <!-- ... include other javascript files -->
  </body>
</html>

这是我包含在每个页面上的 javascript 文件的一部分:

$(function() {
    // Attach csfr data token
    $.ajaxSetup({
       data: csfrData
    });
});
嗨乔治亚尔,谢谢你的建议。我现在可以在页面加载时通过 AJAX 加载数据。我有一个按钮调用相同的函数,在页面加载时触发。但是,当单击时,我收到此错误消息“不允许您请求的操作。”
2021-04-18 18:40:22

你可能想试试我用过的这段代码。它工作得很好:

<script type="text/javascript">
$(function(){
   $('.answerlist').each(function(e){

  $(this).click(function(){

    var valrad = $("input[@name=answer]:checked").val();


    var post_data = {
        'ansid': valrad,
        '<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>'
    };

        $.ajax({
                type: "POST",
                url: "<?php echo base_url(); ?>online/checkanswer",
                data: post_data,
                success: function(msg){
                  /// do something 
                }
            });

  });

   });


});


</script>

如果需要,您可以在适当的地方同时回显令牌名称和哈希值。像这样的东西。

 echo $this->security->get_csrf_token_name()

 echo $this->security->get_csrf_hash()

或者,您可以像往常一样使用 form_open() 并使用从您的 javascript 为您生成的隐藏输入。禁用 CSRF 功能是错误的方法。

回顾我的情况后,我认为最好的选择是使用 CSRF,但在每次尝试时重置令牌。否则,之前表达的关于重新使用 cookie 令牌的想法将允许攻击者使用相同的令牌重新提交数据数百次,这会破坏该点的对象。

因此,我创建了以下函数:

public function resetCSRF(){    

    $this->security = null;

    $_COOKIE[$this->config->item('csrf_cookie_name')] = null;

    load_class('Security', 'core');

    $this->security->csrf_set_cookie();

return $this->security->get_csrf_hash();
}

例如,如果基于 ajax 的登录表单失败 - 在您的 PHP 中调用此函数,然后在接收失败的 javascript 端(此解决方案使用 Jquery 和 w3schools 的 getCookie 函数)将简单地调用:

$('input[name="csrf_test_name"]').val(getCookie('csrf_cookie_name'));

基本上,您需要做的是从 cookie(默认名为“ci_csrf_token”)中获取预期的 csrf 值,然后将其与其他数据一起发布。

您需要修改此行:

$.post(baseurl + 'ajax/images',{'id' : ID}, function(data) {

到:

$.post(baseurl + 'ajax/images',{'id' : ID,'ci_csrf_token' : $.cookie('ci_csrf_token')}, function(data) {

可能需要安装 cookie 插件(我不太确定;我使用的是 mootools)。以下是更多信息:http : //aymsystems.com/ajax-csrf-protection-codeigniter-20