我跑进使用CodeIgniter / CSRF / JSON的问题。
我发送HTTP POST请求我与内容类型“应用/ JSON PHP后台,有效载荷是JSON数据。随着数据,我传递一个生成并存储在CSRF cookie中的CSRF令牌。随着标准的POST FORM请求时,它工作得很好,但作为JSON发送时失败。
由于$ _POST阵列是因为JSON内容类型的空,笨未能验证cookie并引发错误。
我怎么能有笨检查JSON有效载荷和验证我的CSRF令牌?
我跑进使用CodeIgniter / CSRF / JSON的问题。
我发送HTTP POST请求我与内容类型“应用/ JSON PHP后台,有效载荷是JSON数据。随着数据,我传递一个生成并存储在CSRF cookie中的CSRF令牌。随着标准的POST FORM请求时,它工作得很好,但作为JSON发送时失败。
由于$ _POST阵列是因为JSON内容类型的空,笨未能验证cookie并引发错误。
我怎么能有笨检查JSON有效载荷和验证我的CSRF令牌?
或者,也可以跳过CSRF通过添加下列下面351号线中的应用/配置/ config.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;
}
要解决这个问题,我不得不改变位于“Security.php”文件的代码“系统/核心/”。
在功能“csrf_verify”,替换代码:
// 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();
}
该代码首先检查$ _ POST然后,如果没有被发现,它会检查JSON有效载荷。
这样做的理想方式是检查传入的请求Content-Type头值。 但出乎意料的是,它不是简单的做...
如果有人有更好的解决办法,请张贴在这里。
干杯
如果需要重写,最好延长安全库,而不是直接编辑核心文件。
创建应用程序/核心文件My_Security.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;
}
}
布赖恩写,你必须把你的自定义类成/应用/核心/ EX。 My_Security.php
这是我的解决方案,为我工作,我检查应用程序/ JSON CONTENT_TYPE,并要求饼干。
defined('BASEPATH') OR exit('No direct script access allowed');
class MY_Security extends CI_Security {
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();
}
/**
* mine implementation for application/json
*/
$reqHeaders = getallheaders();
$content_type = $reqHeaders["Content-Type"];
#it's a json request?
if(preg_match("/(application\/json)/i",$content_type))
{
#the check the cookie from request
$reqCookies = explode("; ",$reqHeaders["Cookie"]);
foreach($reqCookies as $c)
{
if(preg_match("/(".$this->_csrf_cookie_name."\=)/", $c))
{
$c = explode("=",$c);
if($_COOKIE[$this->_csrf_cookie_name] == $c[1])
{
return $this;
}
}
}
}
//< end
// Check if URI has been whitelisted from CSRF checks
if ($exclude_uris = config_item('csrf_exclude_uris'))
{
$uri = load_class('URI', 'core');
foreach ($exclude_uris as $excluded)
{
if (preg_match('#^'.$excluded.'$#i'.(UTF8_ENABLED ? 'u' : ''), $uri->uri_string()))
{
return $this;
}
}
}
// Do the tokens exist in both the _POST and _COOKIE arrays?
if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
OR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match?
{
$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]);
// Regenerate on every submission?
if (config_item('csrf_regenerate'))
{
// Nothing should last forever
unset($_COOKIE[$this->_csrf_cookie_name]);
$this->_csrf_hash = NULL;
}
$this->_csrf_set_hash();
$this->csrf_set_cookie();
log_message('info', 'CSRF token verified');
return $this;
}
}