CI框架用钩子实现URL权限控制

PHP piniu 763浏览 0评论

CI 的钩子功能使得您可以在不修改系统核心文件的基础上来改变或增加系统的核心运行功能。
例如,您可以在控制器刚刚载入前或刚刚载入后来运行特定的脚本,或者在其他时刻来触发您的脚本。

//对钩子的简单理解

简单的说,钩子就是程序。这些程序可以在特定的时间被调用。
你既然用CI框架,那么应该知道,在框架初始化的过程中,有一些特殊的时间点,比如
(1)、框架初始化之前的时间点。
(2)、控制器初始化之前的时间点
(3)、控制器运行之后的时间点
当然还有其他的时间点。
在每一个时间点,你都可以埋下一些钩子(可以是一段程序,或者一个函数)。框架中都会有一个专门处理钩子的类库(比如CI中的hooks.php),这个Hook类就会在程序运行的特定点检查是不是有特定的钩子,如果有钩子,就执行这个钩子。

说了这么多,可能还是有点抽象。打个比方:
你下班回家的整个流程看做是框架的执行流程,正常情况下,你下班直接走回家就可以。如果你老妈给你打电话说,如果你路过邮局,刚好有咱家的快递,带回家,这个过程,就比较类似钩子(检查钩子,如果有则执行之)。

如果你做过一些前端的工作,这个钩子就恰似“事件驱动”的模式。
看代码:

1. system/application/config/hooks.php中添加钩子声明:

//这里post_controller_constructor 为挂钩点名称 ,可参考:http://codeigniter.org.cn/user_guide/general/hooks.html
$hook['post_controller_constructor'] = array(
 'class' => 'Acl',  
 'function' => 'filter',  
 'filename' => 'acl.php',  
 'filepath' => 'hooks',  
);

2. 在system/application/config/config.php 开启钩子设置

$config['enable_hooks'] = TRUE;

然后在application/config/中新建acl.php权限系统配置文件,当然你也可以放在数据库中。

<?php
//游客权限映射  
$config['acl']['visitor'] = array(  
    '' => array('index'),//首页  
    'music' => array('index', 'list'),  
    'user' => array('index', 'login', 'register')  
);  
//管理员  
$config['acl']['admin'] = array(  
   
);  
   
//-------------配置权限不够的提示信息及跳转url------------------//  
$config['acl_info']['visitor'] = array(  
    'info' => '需要登录以继续',  
    'return_url' => 'user/login'  
);  
   
$config['acl_info']['more_role'] = array(  
    'info' => '需要更高权限以继续',  
    'return_url' => 'user/up'  
);

3. system/application/hooks目录下添加acl.php逻辑处理文件

<?php
 
class Acl  
{  
    private $url_model;//所访问的模块,如:music  
    private $url_method;//所访问的方法,如:create  
    private $url_param;//url所带参数 可能是 1 也可能是 id=1&name=test  
    private $CI;  
   
    function Acl()  
    {  
        $this->CI = & get_instance();  
        $this->CI->load->library('session');  
   
        $url = $_SERVER['PHP_SELF'];  
        $arr = explode('/', $url);  
        $arr = array_slice($arr, array_search('index.php', $arr) + 1, count($arr));  
        $this->url_model = isset($arr[0]) ? $arr[0] : '';  
        $this->url_method = isset($arr[1]) ? $arr[1] : 'index';  
        $this->url_param = isset($arr[2]) ? $arr[2] : '';  
    }  
   
    function filter()  
    {  
        $user = $this->CI->session->userdata('user');  
        if (empty($user)) {//游客visitor  
            $role_name = 'visitor';  
        } else {  
            $role_name = $user->role;  
        }  
   
        $this->CI->load->config('acl');  //加载自定义配置文件(config/acl.php)  可参考:http://codeigniter.org.cn/user_guide/libraries/config.html
        $acl = $this->CI->config->item('acl');  //获取自定义配置文件的数据
        $role = $acl[$role_name];  
        $acl_info = $this->CI->config->item('acl_info');  //获取自定义配置文件的数据
   
        if (array_key_exists($this->url_model, $role) && in_array($this->url_method, $role[$this->url_model])) {  
            ;  
        } else {//无权限,给出提示,跳转url  
            $this->CI->session->set_flashdata('info', $acl_info[$role_name]['info']);  
            redirect($acl_info[$role_name]['return_url']);  
        }  
    }  
}

//附:CI框架中的hooks 挂钩点名称:

以下是所有可用挂钩点的一份列表:

  • pre_system 在系统执行的早期调用,这个时候只有 基准测试类 和 钩子类 被加载了, 还没有执行到路由或其他的流程。
  • pre_controller 在你的控制器调用之前执行,所有的基础类都已加载,路由和安全检查也已经完成。
  • post_controller_constructor 在你的控制器实例化之后立即执行,控制器的任何方法都还尚未调用。
  • post_controller 在你的控制器完全运行结束时执行。
  • display_override 覆盖 _display() 方法,该方法用于在系统执行结束时向浏览器发送最终的页面结果。 这可以让你有自己的显示页面的方法。注意你可能需要使用$this->CI =& get_instance() 方法来获取 CI 超级对象,以及使用 $this->CI->output->get_output() 方法来 获取最终的显示数据。
  • cache_override 使用你自己的方法来替代 输出类 中的 _display_cache() 方法,这让你有自己的缓存显示机制。
  • post_system 在最终的页面发送到浏览器之后、在系统的最后期被调用。

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • * 昵称:
  • * 邮箱: