在application的config中可以开启csrf的设置:
$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = TRUE;
$config['csrf_exclude_uris'] = array();
如果开启后,会在CI的核心类的构造函数中,进行调用:
// CSRF Protection check
if ($this->_enable_csrf === TRUE && ! is_cli())
{
$this->security->csrf_verify();
}
而这个:
$this->security->csrf_verify();
会在非post请求中设置cookie。
/**
* CSRF Verify
*
* @return 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();
}
// 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;
}
}
}
// Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate
$valid = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
&& is_string($_POST[$this->_csrf_token_name]) && is_string($_COOKIE[$this->_csrf_cookie_name])
&& hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]);
// We kill this since we're done and we don't want to pollute 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();
if ($valid !== TRUE)
{
$this->csrf_show_error();
}
log_message('info', 'CSRF token verified');
return $this;
}
$this->security->csrf_verify();
如果是非post请求,则设置cookie,如果是post请求,则校验post请求核cooke是否正确,即token校验。
使用的是,如果是post请求,请在js代码中的post请求中插入数据:
data['csrf_test_name']=getCookie('csrf_cookie_name');
其中:csrf_test_name和csrf_cookie_name为config中设置的。
也可以这样:
data['csrf_test_name']='=$this->security->get_csrf_hash();?>';
或者:
data['=$this->security->get_csrf_token_name();?>']='=$this->security->get_csrf_hash();?>';
值都是一样的。
getCookie函数的代码为:
function getCookie(name){
var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
if(arr != null) return unescape(arr[2]); return null;
}
如果不插入这个,请求返回会报403错误。
在app里面,就不需要做任何验证了,ci已经自动进行了验证,验证完会去掉post请求参数中的csrf的变量。
CodeIgniter 的这个csrf安全会在所有页面中生成csrf的cookie,不管你要不要。
其中config中的这个设置
$config['csrf_exclude_uris'] = array();
是过滤不需要验证的url,cookie还是要生成的。