当前位置: 首页 > 知识库问答 >
问题:

JSON请求中的CodeIgniter CSRF令牌

王锐
2023-03-14

我遇到了CodeIgniter/CSRF/JSON的问题。

我正在向PHP后端发送内容类型为“application/json”的http POST请求。有效负载是json数据。我将与数据一起传递生成并存储在CSRF cookie中的CSRF令牌。对于标准POST表单请求,它工作正常,但作为json发送时失败。

由于$\u POST数组因JSON内容类型而为空,CodeIgniter无法验证cookie并抛出错误。

如何让CodeIgniter检查JSON负载并验证我的CSRF令牌?

共有3个答案

霍建章
2023-03-14

如果需要重写,最好扩展安全库,而不是直接编辑核心文件。

创建文件My_Security。在application/core/中使用php,并添加以下内容(来自上面的解决方案):

<?php
class My_Security extends CI_Security {
    /**
     * Verify Cross Site Request Forgery Protection
     *
     * @return  object
     */
    public function csrf_verify()
    {
        // If it's not a POST request we will set the CSRF cookie
        if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST')
        {
            return $this->csrf_set_cookie();
        }

        // Do the tokens exist in both the _POST and _COOKIE arrays?
        if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])) {
            // No token found in $_POST - checking JSON data
            $input_data = json_decode(trim(file_get_contents('php://input')), true);
            if ((!$input_data || !isset($input_data[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])))
                $this->csrf_show_error(); // Nothing found
            else {
                // Do the tokens match?
                if ($input_data[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name])
                    $this->csrf_show_error();
            }
        }
        else {
            // Do the tokens match?
            if ($_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name])
                $this->csrf_show_error();
        }        // We kill this since we're done and we don't want to

        // polute the _POST array
        unset($_POST[$this->_csrf_token_name]);

        // Nothing should last forever
        unset($_COOKIE[$this->_csrf_cookie_name]);
        $this->_csrf_set_hash();
        $this->csrf_set_cookie();

        log_message('debug', 'CSRF token verified');

        return $this;
    }

}
吴驰
2023-03-14

为了解决这个问题,我必须更改位于“system/core/”中的“Security.php”文件的代码。

功能“csrf_验证”中,替换该代码:

// Do the tokens exist in both the _POST and _COOKIE arrays?
if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]))
{
$this->csrf_show_error();
}
// Do the tokens match?
if ($_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name])
{
$this->csrf_show_error();
}

通过那个代码:

// Do the tokens exist in both the _POST and _COOKIE arrays?
if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])) {
    // No token found in $_POST - checking JSON data
    $input_data = json_decode(trim(file_get_contents('php://input')), true); 
    if ((!$input_data || !isset($input_data[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])))
        $this->csrf_show_error(); // Nothing found
    else {
        // Do the tokens match?
        if ($input_data[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name])
            $this->csrf_show_error();
    }
}
else {
    // Do the tokens match?
    if ($_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name])
        $this->csrf_show_error();
}

该代码首先检查$\u POST,然后如果未找到任何内容,则检查JSON负载。

实现这一点的理想方法是检查传入的请求内容类型头值。但令人惊讶的是,这样做并不直接。。。

如果有人有更好的解决方案,请张贴在这里。

干杯

沙柏
2023-03-14

或者,您可以通过在application/config/config上添加以下代码来跳过CSRF检查。第351行下方的php(基于CI 2.1.4)。

 $config['csrf_expire'] = 7200; // This is line no. 351

/* If the REQUEST_URI has method is POST and requesting the API url,
    then skip CSRF check, otherwise don't do. */
if (isset($_SERVER["REQUEST_URI"]) &&
   (isset($_SERVER['REQUEST_METHOD']) && ($_SERVER['REQUEST_METHOD'] == 'POST') ))
{
    if (stripos($_SERVER["REQUEST_URI"],'/api/') === false )  { // Verify if POST Request is not for API
        $config['csrf_protection'] = TRUE;
    }
    else {
        $config['csrf_protection'] = FALSE;
    }
} else {
    $config['csrf_protection'] = TRUE;
}
 类似资料:
  • 问题内容: 如何用Java发出HTTP Json请求?有图书馆吗?在“ HTTP Json请求”下,我的意思是使用Json对象作为数据进行POST,并以Json接收结果。 问题答案: 除了本身进行HTTP请求(甚至可以仅使用 **java.net.URL.openConnection** 即可完成)之外,您还需要一个JSON库。为了方便地与POJO绑定,我建议使用Jackson。 因此,类似: (

  • 问题内容: 进行Ajax调用时,将contentType设置为application / json而不是默认的x-www-form- urlencoded时,服务器端(在PHP中)无法获取post参数。 在以下工作示例中,如果我在ajax请求中将contentType设置为“ application / json”,则PHP $ _POST将为空。为什么会这样?如何在PHP中正确处理content

  • 概述 我将使用API网关作为基于Spring Security性的身份验证。我刚刚按照https://spring.io/guides/tutorials/spring-security-and-angular-js/链接中的步骤创建了一个基于其对应的github项目的“对双”模块的项目https://github.com/spring-guides/tut-spring-security-and

  • 问题内容: 我想仅使用本机Python库将JSON编码的数据发送到服务器。我喜欢请求,但我根本无法使用它,因为我无法在运行脚本的计算机上使用它。我需要没有它。 我的服务器是本地WAMP服务器。我总是得到一个 urllib.error.HTTPError:HTTP错误500:内部服务器错误 我 100%确信 这 不是 服务器问题,因为在同一台计算机上,同一台服务器上的同一数据,相同的url与请求库和

  • 问题内容: 我已经在Java中生成了一个包含JSON对象的HTMLPost请求,并希望在PHP中对其进行解析。 并在服务器上 我猜这是因为JSON特殊字符已编码。 json_decode返回空响应 知道为什么吗? 问题答案: 实际上,您不是在发布实体,而是在发布具有单个值对json =(encoded json)的HTTP表单实体()。 代替 尝试