|
本帖最后由 qingxin 于 2013-1-8 21:17 编辑
因为觉得ci的csrf防御既不方便也不是十分安全,所以自己构建了一个csrf防御规则,我是放在扩展MY_Controller的_remap()函数里的,示例代码仅供参考,具体细节视实际开发环境而定。
首先,一定要在ci的配置里关闭自带csrf机制,不知道怎么做的请仔细阅读手册。
以下是示例代码
PHP复制代码
public function _remap ($method = NULL, $params = array())
{
$go = TRUE;
//自建跨站请求防御以取代CI的并不方便也不十分安全的跨站请求防御
if(empty($_COOKIE['token']))
{
$uniqid = uniqid();
setcookie('token',$uniqid,0,'/');//注意:一定要设置cookie的存储路径
}
else
{
$uniqid = $_COOKIE['token'];
}
if(!empty($_POST))
{
$token = $this->input->get_post('token');
if($token === saltedhash ($uniqid,$token))
{
$go = TRUE;
if(!is_ajax ())
{
$uniqid = uniqid();
setcookie('token',$uniqid,0,'/');//注意:一定要设置cookie的存储路径
}
}
else
{
$go = FALSE;
show_error ('Your request is not allowed.');
}
}
$this->data['token'] = saltedhash ($uniqid);
if($go)
{
if (!empty($method) && method_exists($this, $method)) call_user_func_array(array($this, $method), $params);
$this->__output ();
}
}
复制代码
说明:
1.saltedhash()是自定义加密函数,保证每次令牌明文是一段不可预知的字符串,仅具有比对功能,也就是说它的加密是不可逆转的,读者也可以使用其他加密思路。
2.__output()是模板加载函数,他会把data属性传出到模板变量。
3.请主要参考防御过程,前两条说明仅仅是提供一些额外的思路。
此防御规则的优点:
1.同步请求时,验证通过时销毁令牌并重新生成;异步请求时,不销毁令牌,可通过get变量传递令牌(写到这里突然想到一个问题,csrf防御的是防御来自第三方的表单伪造,并不是用来防止恶意重复提交的,这点请读者牢记,虽然本防御机制在同步请求的情况下可以防止表单重复提交,但是异步请求的情况下就无能为力了,可以通过更复杂的前后端交互机制来解决这个问题)。与ci自带的csrf的区别是此防御机制以验证是否通过作为是否更换令牌的依据并且可通过get参数传递,主要解决异步上传图片的问题;ci是以时间为依据更换令牌的,并且不能通过get方式传递。
2.正如上面所说,在一定程度上防止表单重复提交。
3.令牌储存在cookie里,通过加密的方式传出,防止第三方代码通过读取cookie获取令牌,也就是说,cookie里的明文令牌是无法通过验证的。
4.由于cookie的延迟特性,所以需要一个中间变量使它达到session的即设即用效果。
|
|