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

[权限控制] 利用CI钩子实现权限认证

  [复制链接]
发表于 2011-11-3 00:13:13 | 显示全部楼层 |阅读模式
文章来源:重庆PHP
转载:http://www.php-chongqing.com/index.php/article/79

一直没找到CI的权限认证扩展,以前好像找到过一个老外的扩展,不过不怎么好用,现在记不清了,后来仿着jsp firter的方式用CI钩子写了一下,感觉还可以,做个小网站,小应用足够了,没必要搞得太复杂。看到很多人在网上问,这里把我们的方法分享一下,如果你有更好的实现,也请记得分享给我们。^_^

通常我们后台路径看起来都会像下面这样:

http://www.php-chongqing.com/index.php/manage/

http://www.php-chongqing.com/index.php/manage/article/add

http://www.php-chongqing.com/index.php/manage/product/delete/1

http://www.php-chongqing.com/index.php/manage/user


因为CI是MVC的,单一入口,并且给我们提供了7个挂钩点,一切就很简单了,我们只需要在CI执行目标控制器方法之前拦截到请求,检查URI是否是以manage开头即可,如果URI以manage开头,就检查用户权限,没有权限就跳转到登陆页或是相关的提示页。


1、先到config/config.php中设置允许使用钩子

$config['enable_hooks'] = TRUE;
2、再到config/hooks.php中配置权限认证钩子

$hook['post_controller_constructor'] = array(    'class'    => 'ManageAuth',    'function' => 'auth',    'filename' => 'ManageAuth.php',    'filepath' => 'hooks');
需要注意的是一定要使用'post_controller_constructor'挂钩点,因为我们可能要在ManageAuth中使用CI的aip,连接数据库等。


3、创建ManageAuth.php文件,放到hooks目录下,ManageAuth.php中的代码如下:

/** * * 后台权限拦截钩子 * @link http://www.php-chongqing.com * @author bing.peng *  */class ManageAuth {    private $CI;            public function __construct() {        $this->CI = &get_instance();     }            /**     * 权限认证     */    public function auth() {        $this->CI->load->helper('url');        if ( preg_match("/manage.*/i", uri_string()) ) {        // 需要进行权限检查的URL            $this->CI->load->library('session');            if( !$this->CI->session->userdata('username') ) {        // 用户未登陆                redirect('login');                return;            }        }            }        }

OK,就这样,搞定了,我们通过正则表达匹配,凡是以manage打头的url都是需要登陆后才能访问的。

示例中的权限认证很简单,仅仅只是检查下session是否存有username,如果有就认为用户已登陆,可以访问资源,否则就跳转到登陆页面。注意登陆的url千万不是能以manage开头,否则就重向定死循环了。


如果,你须更复杂的权限认证直接写你自己的认证方法就OK了,比如你使用了用户、角色、资源等等。


这种实现基本可以算作AOP(面向切面编程)了,其实PHP已经有了AOP的雏形,改天用原生PHP的方法拦截,实现一下权限认证。^_^



本帖被以下淘专辑推荐:

发表于 2011-11-3 18:23:04 | 显示全部楼层
这个功能我是通过MY_Controller类实现的
我的所有控制器都是继承MY_Controller而不是CI_Controller

点评

hook是自动调用吗?不会吧.如果定义多个勾子,那不是全调用了吗.  发表于 2011-11-8 13:29
发表于 2017-2-7 13:49:57 | 显示全部楼层
terryliu 发表于 2016-9-27 10:36
在钩子里不错,看了githup老外不少oauth也是这么弄。一般在配置里有个地方设置免验证的路径供登录时候界面 ...

自己写个 My_Controller继承CI_Controller。My_Controller的构造器函数中定义检测函数。然后让其他的controller继承My_Controller也可以实现。
发表于 2016-9-27 10:36:02 | 显示全部楼层
在钩子里不错,看了githup老外不少oauth也是这么弄。一般在配置里有个地方设置免验证的路径供登录时候界面用。其他的可以用rbac来搞。

只能说钩子只是个触发验证的地方,具体实现还得要做很多工作
发表于 2011-11-3 08:39:33 | 显示全部楼层
顶一下,道理是这样的。

不过如果想实现更复杂的权限控制,还是有很多工作要做。
发表于 2011-11-3 09:37:11 | 显示全部楼层
这个还是比较实用的,之前我用把这个放到每个控制器的construct里,不过每个都需要放上,比较重复,用这个就比较方便了,然后再加上我的二进制位运算判断就可以做多权限控制了
发表于 2011-11-23 09:17:52 | 显示全部楼层
我也是通过继承CI_Controller去实现权限控制的,同上
发表于 2011-11-23 15:04:49 | 显示全部楼层
好东西,受教了
发表于 2011-11-23 21:08:25 | 显示全部楼层
acabin 发表于 2011-11-3 18:23
这个功能我是通过MY_Controller类实现的
我的所有控制器都是继承MY_Controller而不是CI_Controller ...

我刚学CI,能不能教教我如何写这个My_Controller类,文件名是什么?放在哪个目录下。
发表于 2011-11-23 21:08:37 | 显示全部楼层
acabin 发表于 2011-11-3 18:23
这个功能我是通过MY_Controller类实现的
我的所有控制器都是继承MY_Controller而不是CI_Controller ...

我刚学CI,能不能教教我如何写这个My_Controller类,文件名是什么?放在哪个目录下。
发表于 2011-11-24 00:21:53 | 显示全部楼层
meditator 发表于 2011-11-23 21:08
我刚学CI,能不能教教我如何写这个My_Controller类,文件名是什么?放在哪个目录下。 ...

手册,创建核心系统类
发表于 2011-11-24 11:42:29 | 显示全部楼层
acabin 发表于 2011-11-24 00:21
手册,创建核心系统类

看了,已经测试成功,多谢了。

本版积分规则