【问题标题】:Ajax call crash on CodeIgniter - CSRF Error 403CodeIgniter 上的 Ajax 调用崩溃 - CSRF 错误 403
【发布时间】:2015-10-06 16:26:36
【问题描述】:

我正在尝试在 CodeIgniter 中执行 Ajax 调用。如前所述,当 CSRF 保护处于活动状态时,必须将哈希(随机生成)与每个请求一起提交给服务器。

在研究中,我发现以下代码始终通过 Ajax 请求与其他数据一起发送散列:

$.ajaxSetup({
    data: {
        arquivo_facil_tk: $.cookie('arquivo_facil_co')
    }
});

所以我在页面加载后的第一次调用中得到了肯定的结果。但是要尝试第二次调用,得到错误 403。我还找到了为我进行的每个 Ajax 调用添加此代码 sn-p 的选项,但是当我的软件执行多次调用时,它变得不可行且粗鲁。

我该如何解决这个问题?也尝试使用 beforeSend 事件,但得到了同样的错误。

【问题讨论】:

    标签: php ajax codeigniter security csrf


    【解决方案1】:

    而不是使用 ajaxSetup,只需在您的实际 AJAX 调用中包含 CSRF 令牌和 data,如下所示:

    data: {var: value, arquivo_facil_tk: $.cookie('arquivo_facil_co')}
    

    或者如果您只是简单地序列化表单:

    data: $(this).serialize() + '&arquivo_facil_tk=' + $.cookie('arquivo_facil_co')
    

    【讨论】:

    • 好的,很好。但是我在应用程序的生命周期和几个不同的功能中进行了几次调用。我没有办法将这些数据作为所有呼叫的标准数据吗?
    【解决方案2】:

    问题在于 csrf 令牌仅对一次调用有效,因此如果您想在另一个发布请求上使用 ajax 而不刷新页面,您需要以某种方式获取新令牌而不重新加载表单。您可以在您的 codeigniter 控制器中通过将新令牌发送回请求脚本来执行此操作。

    在您的 CodeIgniter 控制器中:

    $data = array('data'=> 'data to send back to browser');
    $csrf =  $this->security->get_csrf_hash();
    $this->output
        ->set_content_type('application/json')
        ->set_output(json_encode(array('data' => $data, 'csrf' => $csrf)));
    

    $data = 返回给浏览器的数据

    $csrf = 浏览器用于下一个 ajax 发布请求的新 csrf 令牌

    显然,您可以通过其他方式输出它,但 JSON 主要用于 ajax 调用。还要在每个发布响应中以这种方式包含令牌,以用于下一个发布请求

    然后在你的下一个 ajax 请求(javascript)中:

    var token = data.csrf;
    
    $.ajax({
        url: '/next/ajax/request/url',
        type: 'POST',
        data: { new_data: 'new data to send via post', csrf_token:token },
        cache: false,
        success: function(data, textStatus, jqXHR) {
            // Get new csrf token for next ajax post
            var new_csrf_token = data.csrf     
           //Do something with data returned from post request
        },
        error: function(jqXHR, textStatus, errorThrown) {
          // Handle errors here
          console.log('ERRORS: ' + textStatus + ' - ' + errorThrown );
        }
    });
    

    还请记住,我在哪里找到了 csrf_token:token,将 crf_token 替换为您在 application/config/config.php 中找到的令牌的名称,上面写着 $config['csrf_token_name'] = 'csrf_token';

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题。解决方案?我在整个系统中使用一个 CSRF 令牌,仅在登录/注销(和类似功能)时更改。

      为了避免来自同一个表单的多次提交(比如双击甚至攻击),当我调用表单时,我还会在事务表中插入一个随机 ID。

      当我收到此表格时,我会检查交易表中的 ID。如果存在,请执行操作并从事务表中删除 ID。如果不是,则显示消息错误。

      【讨论】:

        猜你喜欢
        • 2015-12-12
        • 2011-09-06
        • 2023-03-08
        • 2017-03-23
        • 1970-01-01
        • 2014-08-21
        • 1970-01-01
        • 1970-01-01
        • 2017-01-25
        相关资源
        最近更新 更多