【问题标题】:CodeIgniter CSRF failing on formsCodeIgniter CSRF 在表单上失败
【发布时间】:2018-07-16 11:48:03
【问题描述】:

注意:这个问题不是关于失败的 AJAX 请求,而是关于失败的常规表单提交。

我在 CodeIgniter 3 中启用了 CSRF 保护,使用以下config.php

$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_token_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = TRUE;

我在表单字段中正确使用了form_open(),以便自动生成包含 CSRF 令牌的所需隐藏字段。但是,当我在我的网站上提交任何表单时,它会导致“遇到错误 - 不允许您请求的操作”。错误。

Cookie 设置:

$config['cookie_prefix'] = '';
$config['cookie_domain'] = '';
$config['cookie_path'] = '/';
$config['cookie_secure'] = FALSE;
$config['cookie_httponly'] = FALSE;

会话设置:

$config['sess_driver'] = 'database';
$config['sess_cookie_name'] = 'ci_session';
$config['sess_expiration'] = 2592000; // one month in seconds
$config['sess_save_path'] = 'ci_sessions';
$config['sess_match_ip'] = TRUE;
$config['sess_time_to_update'] = 300;
$config['sess_regenerate_destroy'] = FALSE;

此外,与大多数关于 CI CSRF 保护的问题相反,我的 AJAX 请求中的 CSRF 令牌确实可以通过将以下 sn-p 添加到我的初始 JavaScript 中正常工作:

function getCookie(c_name) { // A javascript function to get the cookie value
    if(document.cookie.length > 0) {
        c_start = document.cookie.indexOf(c_name + "=");
        if(c_start != -1) {
            c_start = c_start + c_name.length + 1;
            c_end = document.cookie.indexOf(";", c_start);
            if(c_end == -1) c_end = document.cookie.length;
            return unescape(document.cookie.substring(c_start,c_end));
        }
    }
    return "";
}

$.ajaxPrefilter(function(options, originalOptions, jqXHR){ // This function will attach "csrf_test_name" with all the request you are sending.
    if (options.type.toLowerCase() === "post") { // Required only if its a post method
        var csrf_token = getCookie("csrf_cookie_name");
        // initialize `data` to empty string if it does not exist
        options.data = options.data || "";

        // add leading ampersand if `data` is non-empty
        options.data += options.data?"&":"";

        // add _token entry
        options.data += "csrf_token_name=" + csrf_token;
    }
});

有什么方法可以让我的 CSRF 保护在表单字段中发挥作用?另外,我在 cookie 中的 csrf_cookie_name 值与隐藏的 HTML 字段中的 csrf_token_name 值不同,这应该发生吗?

【问题讨论】:

    标签: php forms codeigniter csrf codeigniter-3


    【解决方案1】:

    这是因为 CSRF 令牌在每个 AJAX 请求上重新生成。您可以通过将 $config['csrf_regenerate'] 选项设置为 FALSE 来解决此问题,或者您可以使用 jquery 或 javascript手动更新每个 AJAX 请求上的 csrf 令牌

    查看这篇文章的实现:When CodeIgniter’s CSRF Protection breaks your Ajax

    这个answer by PaulD也很棒。

    【讨论】:

    • 但是提交表单不是 AJAX 请求,对吧?
    • @Stan : 如果你正常提交表单并且整个表单在表单提交后再次重建,那么它不会引起任何问题。
    • 但确实如此。我使用带有form_open() 的普通表单来生成CSRF 隐藏输入字段。在没有任何 AJAX 请求的情况下正常提交。仍然出现错误。
    • 您是否使用表单助手来构建您的表单?你能粘贴你的表单 HTML 代码吗?
    • 是的,form_open() 来自表单助手类。此处的 HTML 代码:pastebin.com/raw/ykXP0fFG
    【解决方案2】:

    我多次遇到这个问题。这是让我烦恼的问题之一 :)) 。问题似乎是这样一个事实,即通过向某个控制器发出 ajax 请求会重新生成令牌,因此您发送之前生成的令牌,从而导致令牌不匹配。我通过禁用 csrf_regenerate 解决了我的问题。我知道它不安全,但它让事情顺利进行。

    【讨论】:

      猜你喜欢
      • 2017-06-25
      • 2015-08-26
      • 2014-01-03
      • 2014-02-25
      • 1970-01-01
      • 1970-01-01
      • 2020-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多