在ci里构建自己的csrf防御机制
本帖最后由 qingxin 于 2013-1-8 21:17 编辑因为觉得ci的csrf防御既不方便也不是十分安全,所以自己构建了一个csrf防御规则,我是放在扩展MY_Controller的_remap()函数里的,示例代码仅供参考,具体细节视实际开发环境而定。
首先,一定要在ci的配置里关闭自带csrf机制,不知道怎么做的请仔细阅读手册。
以下是示例代码
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的即设即用效果。
更正:此防御一定程度上防止表单重复提交(页面后退、页面刷新或其他浏览器默认行为造成)但不能防止表单恶意提交(用户恶意提交) 这个具体是怎么使用的? ahkxhyl 发表于 2013-1-7 20:49 static/image/common/back.gif
这个具体是怎么使用的?
看说明再加上自己琢磨,别人的永远是别人的,只有自己认真思考之后才能真正成为自己的东西,因为表单跨站防御是一种思想或者说一种思路,没办法像一个功能函数那样复制粘贴就能用的。
如果耐心不够的话,是不适合做程序的。其实程序很简单,但是只有理解了某个关键的东西才能一通百通。没有高手和低手,只在于,你,愿不愿意真正地去想去思考一个问题。
页:
[1]