用户
 找回密码
 入住 CI 中国社区
搜索
查看: 15962|回复: 14
收起左侧

[核心代码 Core] URL 分段传参验证钩子,增强 CI 缓存防攻击的能力

    [复制链接]
发表于 2010-7-22 11:51:21 | 显示全部楼层 |阅读模式
关于 CI 缓存问题的讨论很早就进行过了,先来个传送门 http://codeigniter.org.cn/forums/thread-1929-1-1.html

其中一个我认为可以由 CI 自动处理的就是阻止通过 URL 传递任意个数的参数,然后再由程序员自己判断每个参数是否合法,合法则缓存,否则直接 404 错误。(判断是否合法的方法有很多,比如到数据库中验证 ID 是否存在等等。。。)

判断控制器方法的参数个数用到了 PHP5 的反射(Reflection),这方面的知识,可以参考 PHP 手册

在 CI 中我使用了钩子(Hook)来进行自动验证。

首先在 application/config/config.php 中设置:
PHP复制代码
$config['enable_hooks'] = TRUE;
复制代码

然后在 application/config/hooks.php 中设置:
PHP复制代码
$hook['pre_controller'] = array(
        'class'    => 'UriArgs',
        'function' => 'validate_args',
        'filename' => 'UriArgs.php',
        'filepath' => 'hooks'
);
复制代码

最后在 application/hooks 目录中添加 UriArgs.php 文件:
PHP复制代码
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 
class UriArgs {
 
        public function validate_args()
        {
                $RTR =& load_class('Router');
 
                $class  = $RTR->fetch_class();
                $method = $RTR->fetch_method();
 
                if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($class))) )
                {
                        show_404("{$class}/{$method}");
                }
 
                $class_reflection = new ReflectionClass($class);
                $method_reflection = $class_reflection->getMethod($method);
                $URI =& load_class('URI');
                $argnum = count(array_slice($URI->rsegments, 2));
                if ($method_reflection->getNumberOfRequiredParameters() > $argnum || $method_reflection->getNumberOfParameters() < $argnum)
                {
                        show_404("{$class}/{$method}");
                }
        }
 
}
 
/* End of file UriArgs.php */
/* Location: ./system/application/hooks/UriArgs.php */
复制代码

经过以上设置,URL 分段传参的个数必须严格和方法定义的参数一致,否则将报 404 错误,这就在一定程度上防止了恶意缓存攻击的可能性。

附上 CI 钩子手册:http://codeigniter.org.cn/user_guide/general/hooks.html
此代码主要参考了:http://codeigniter.com/forums/viewthread/128873/

注意:此代码只支持 PHP 5.0.3 以上版本!

如果大家发现什么问题,或者有不清楚的地方,请及时反馈!
发表于 2014-10-31 18:17:12 | 显示全部楼层
支持老大,,,,有时间看看
发表于 2010-7-22 12:54:23 | 显示全部楼层
支持老大占沙发
发表于 2010-7-22 15:51:01 | 显示全部楼层
嗯!这个方法好像确实还不错
发表于 2010-7-22 18:21:32 | 显示全部楼层
恩,这个在一定程度上解决了CI自身缓存的不足
发表于 2010-7-24 20:14:07 | 显示全部楼层
可以放心大量用缓存了
发表于 2010-8-8 16:01:49 | 显示全部楼层
用了这个方法后,分页用不了了~
发表于 2010-8-8 16:03:11 | 显示全部楼层
$argnum = count(array_slice($URI->rsegments, 2));

把2改成3就好了
 楼主| 发表于 2010-8-8 21:14:04 | 显示全部楼层
用了这个方法后,分页用不了了~
redlink 发表于 2010-8-8 16:01



    这个和分页无关,关键的地方是你的控制器的方法的参数必须和通过 URL 传递进来的一样。分页的页数参数只要写个默认值就可以了。
发表于 2011-1-3 15:50:01 | 显示全部楼层
支持老大
发表于 2011-1-3 18:18:34 | 显示全部楼层
好方法,老大好样的~~

本版积分规则