• php ci框架使用qeephp框架的acl实现权限验证


    1、在libraries文件夹下添加Acl.php类库

    View Code
      1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
      2 /**
      3  * ACL 实现了权限检查服务
      4  *
      5  * “基于角色”通过比对拥有的角色和访问需要的角色来决定是否通过权限检查。
      6  *
      7  * 在进行权限检查时,要求分别提供角色组和访问控制列表(ACL)。
      8  * 然后由 QACL 比对角色组和 ACL,并返回检查结果。
      9  *
     10  * rolesBasedCheck() 用于比对权限,并返回结果。
     11  * role_normalize() 方法用于将 roles 角色配置 转换为符合规范的 数组形式。
     12  * acl_normalize() 方法用于将 ACL 转换为符合规范的 ACL。
     13  */
     14 class Acl
     15 {
     16     /**
     17      * 预定义角色常量
     18      */
     19     const ACL_EVERYONE    = 'acl_everyone';
     20     const ACL_NULL        = 'acl_null';
     21     const ACL_NO_ROLE     = 'acl_no_role';
     22     const ACL_HAS_ROLE    = 'acl_has_role';
     23     const ALL_CONTROLLERS = 'all_controllers';
     24     const ALL_ACTIONS     = 'all_actions';
     25 
     26     var $uri = array('space'=>'','controller'=>'','action'=>'');
     27     var $acl;
     28     var $acl_controller;
     29     var $acl_action;
     30     var $roles;
     31 
     32     function __construct(){
     33         if(function_exists('get_instance') && class_exists('CI_Controller')){
     34             $CI =& get_instance();
     35             $this->uri = array(
     36                 'space' => $CI->router->fetch_directory(),
     37                 'controller' => $CI->router->fetch_class(),
     38                 'action' => $CI->router->fetch_method()
     39             );
     40         }
     41     }
     42     
     43     /**
     44      * 对 roles 进行权限验证
     45      * @param array $roles
     46      * @param array $acl_uri    space空间命名(CI中的controllers/下dir分目录)    controller控制器文件    action为控制器处理函数
     47      * @param array $acl        自定义权限验证配置
     48      * @return array
     49      */
     50     function checkAcl($roles, $uri = array(),$acl = array()){
     51         if(!empty($uri))    $this->uri = array_merge($this->uri,$uri);
     52         $acl_file = 'acl';
     53         if(isset($this->uri['space'])){
     54             if(!empty($this->uri['space'])){
     55                 $acl_file .= '_'.$this->uri['space'];
     56             }
     57         }
     58         if(empty($acl)){
     59             $filepath = APPPATH.'config/'.$acl_file.'.php';
     60             if (!file_exists($filepath)) return TRUE;
     61         }
     62         $this->roles = $this->roles_normalize($roles);
     63         include($filepath);
     64         $this->acl = $acl;
     65         $this->acl_controller = $this->_controllerACL($this->uri['controller']);
     66         return $this->_actionACL($this->uri['action']);
     67     }
     68     
     69     /**
     70      * 对 roles 整理,返回整理结果
     71      * @param array $roles
     72      * @return array
     73      */
     74     function roles_normalize($roles){
     75         if (!is_array($roles)){    $roles = explode(',', $roles);    }
     76         return array_map('strtolower',array_filter(array_map('trim',$roles),'strlen'));
     77     }
     78     
     79     /**
     80      * 对 ACL 整理,返回整理结果
     81      * @param array $acl 要整理的 ACL
     82      * @return array
     83      */
     84     function acl_normalize(array $acl){
     85         $acl = array_change_key_case($acl, CASE_LOWER);
     86         $ret = array();
     87         $keys = array('allow', 'deny');
     88         foreach ($keys as $key){
     89             do{
     90                 if (!isset($acl[$key])){    $values = self::ACL_NULL;    break;    }
     91                 $acl[$key] = strtolower($acl[$key]);
     92                 if($acl[$key] == self::ACL_EVERYONE || $acl[$key] == self::ACL_HAS_ROLE 
     93                 || $acl[$key] == self::ACL_NO_ROLE || $acl[$key] == self::ACL_NULL){
     94                     $values = $acl[$key];    break;
     95                 }
     96                 $values = $this->roles_normalize($acl[$key]);
     97                 if (empty($values)){    $values = self::ACL_NULL;    }
     98             }while (FALSE);
     99             $ret[$key] = $values;
    100         }
    101         return $ret;
    102     }
    103     
    104     /**
    105      * 对 controller 访问控制做处理
    106      * @param string $controller
    107      * @return array
    108      */
    109     protected function _controllerACL($controller){
    110         if(isset($this->acl[$controller])){
    111             $this->acl = array_change_key_case($this->acl, CASE_LOWER);
    112             return (array)$this->acl[$controller];
    113         }
    114         return isset($this->acl[self::ALL_CONTROLLERS]) ? (array)$this->acl[self::ALL_CONTROLLERS]
    115             : array('allow' => self::ACL_EVERYONE);
    116     }
    117         
    118     /**
    119      * 对 action 访问控制做处理
    120      * @param string $action
    121      * @return array
    122      */
    123     protected function _actionACL($action){
    124         if(isset($this->acl_controller['actions'][$action])){
    125             return $this->_rolesBasedCheck($this->acl_controller['actions'][$action]);
    126         }
    127         if(isset($this->acl_controller['actions'][self::ALL_ACTIONS])){
    128             return $this->_rolesBasedCheck($this->acl_controller['actions'][self::ALL_ACTIONS]);
    129         }
    130         if(isset($this->acl_controller)){
    131             return $this->_rolesBasedCheck($this->acl_controller);
    132         }
    133     }
    134     
    135     /**
    136      * 进行实际权限校验
    137      * @param string $acl
    138      * @return array
    139      */
    140     protected function _rolesBasedCheck($acl){
    141         $this->acl_action = $this->acl_normalize($acl);
    142         if ($this->acl_action['allow'] == self::ACL_EVERYONE){
    143             // 如果 allow 允许所有角色,deny 没有设置,则检查通过
    144             if ($this->acl_action['deny'] == self::ACL_NULL){    return TRUE;    }
    145 
    146             // 如果 deny 为 acl_no_role,则只要用户具有角色就检查通过
    147             if ($this->acl_action['deny'] == self::ACL_NO_ROLE){
    148                 if (empty($this->roles)){    return FALSE;    }
    149                 return TRUE;
    150             }
    151 
    152             // 如果 deny 为 acl_has_role,则只有用户没有角色信息时才检查通过
    153             if ($this->acl_action['deny'] == self::ACL_HAS_ROLE){
    154                 if (empty($this->roles)){    return TRUE;    }
    155                 return FALSE;
    156             }
    157 
    158             // 如果 deny 也为 acl_everyone,则表示 acl 出现了冲突
    159             if ($this->acl_action['deny'] == self::ACL_EVERYONE){
    160                 return FALSE;
    161             }
    162 
    163             // 只有 deny 中没有用户的角色信息,则检查通过
    164             foreach ($this->roles as $role){
    165                 if (in_array($role, $this->acl_action['deny'])){    return FALSE;    }
    166             }
    167             return TRUE;
    168         }
    169 
    170         do{
    171             // 如果 allow 要求用户具有角色,但用户没有角色时直接不通过检查
    172             if ($this->acl_action['allow'] == self::ACL_HAS_ROLE){
    173                 if (!empty($this->roles)){    break;    }
    174                 return FALSE;
    175             }
    176 
    177             // 如果 allow 要求用户没有角色,但用户有角色时直接不通过检查
    178             if ($this->acl_action['allow'] == self::ACL_NO_ROLE){
    179                 if (empty($this->roles)){    break;    }
    180                 return FALSE;
    181             }
    182 
    183             if ($this->acl_action['allow'] != self::ACL_NULL){
    184                 // 如果 allow 要求用户具有特定角色,则进行检查
    185                 $passed = FALSE;
    186                 foreach ($this->roles as $role){
    187                     if (in_array($role, $this->acl_action['allow'])){
    188                         $passed = TRUE;
    189                         break;
    190                     }
    191                 }
    192                 if (!$passed){    return FALSE;    }
    193             }
    194         } while (FALSE);
    195 
    196         // 如果 deny 没有设置,则检查通过
    197         if ($this->acl_action['deny'] == self::ACL_NULL){    return TRUE;    }
    198 
    199         // 如果 deny 为 acl_no_role,则只要用户具有角色就检查通过
    200         if ($this->acl_action['deny'] == self::ACL_NO_ROLE){
    201             if (empty($this->roles)){    return FALSE;    }
    202             return TRUE;
    203         }
    204         // 如果 deny 为 acl_has_role,则只有用户没有角色信息时才检查通过
    205         if ($this->acl_action['deny'] == self::ACL_HAS_ROLE){
    206             if (empty($this->roles)){    return TRUE;    }
    207             return FALSE;
    208         }
    209 
    210         // 如果 deny 为 acl_everyone,则检查失败
    211         if ($this->acl_action['deny'] == self::ACL_EVERYONE){    return FALSE;    }
    212 
    213         // 只有 deny 中没有用户的角色信息,则检查通过
    214         foreach ($this->roles as $role){
    215             if (in_array($role, $this->acl_action['deny'])){    return FALSE;    }
    216         }
    217         return TRUE;
    218     }
    219 }
    220 // END Controller class
    221 
    222 /* End of file Acl.php */
    223 /* Location: ./application/libraries/Acl.php */

     2、在项目文件夹下的core文件夹中创建核心类MY_Controller.php,在该文件中添加权限验证,所有需要验证的控制器文件都要继承该类。

     1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
     2 
     3 class Auth_Controller extends CI_Controller {
     4     
     5     var $role = '';
     6     var $uid = 0;
     7     var $username = '';
     8     
     9     var $_ckey='';
    10     var $_akey='';
    11     var $_mkey='';
    12     
    13     function __construct()
    14     {
    15         parent::__construct();
    16                 //引入Acl类库
    17         $this->load->library(array('Acl','common'));
    18 
    19         //假设现在角色为admin,这里可以自已定义获取角色权限的方法。
    20                 $this->role = 'gm';
    21                 //执行权限判断
    22         if(!$this->acl->checkAcl( $this->role )){
    23             if( method_exists($this,'_on_access_denied') ) $this->_on_access_denied();
    24         }
    25         
    26         
    27     }
    28     
    29     /*
    30      * @name _on_access_denied 访问无权限时处理方法
    31      * @return null
    32      */
    33     protected function _on_access_denied()
    34     {
    35         header('Content-type: text/html; charset=utf-8');
    36         echo '无权限';exit;
    37 //        header('Location: '.config_item('sso_admin_url').'?ref='.urlencode(config_item('ref_url')));exit;
    38     }
    39     
    40     protected function _db_error(){
    41         echo 'DB_error();';exit;
    42     }
    43     
    44     protected function _redirectMessage($heading,$message,$url,$time=5,$hidden_script='')
    45     {
    46         $this->load->view('common/show_msg',array('message_caption'=>$heading,'message_body'=>$message,'redirect_url'=>$url,'redirect_delay'=>$time,'hidden_script'=>$hidden_script));
    47         return;
    48     }
    49     
    50     protected function _FailMessage($info,$msg,$url = array()){
    51         if(is_array($url)) $url = $this->common->Get_Url($url);
    52         return $this->_redirectMessage($this->common->Get_ErrorMsg($info),$this->common->Get_ErrorMsg($msg),$url);
    53     }
    54 }
    55 // END Controller class
    56 
    57 /* End of file Auth_Controller.php */
    58 /* Location: ./application/libraries/Auth_Controller.php */            

    3、权限配置文件,在项目的config文件夹下添加acl.php文件,格式参考下面的示例代码。

    该文件中配置了testacl控制器的访问权限为ACL_HAS_ROLE,即所有拥有角色的用户都有权限访问。

    actions中配置的是testacl控制器中index方法和add方法的访问权限。“allow”表示可以访问的角色,“deny”表示不允许访问的角色。

     1 <?php
     2 if ( ! defined('BASEPATH')) exit('No direct script access allowed');
     3 //遵循qeephp中的acl规则
     4 $acl['all_controllers'] = array(
     5     'allow'=>'ACL_HAS_ROLE',//表示所有拥有角色的用户
     6 );
     7 $acl['testacl'] = array(
     8     'allow'=>'ACL_HAS_ROLE',
     9     'actions'=>array(
    10         'index'=>array('allow' => 'admin,editor,gm'),
    11         'add' => array('allow'=> 'admin,editor'),
    12     ),
    13 );

    Acl中预定义的角色常量如下:

     ACL_EVERYONE = 'acl_everyone';     // 所有用户

     ACL_NULL = 'acl_null';                     // 未设置

    ACL_NO_ROLE = 'acl_no_role';         // 没有角色用户

    ACL_HAS_ROLE = 'acl_has_role';     // 有角色用户

    ALL_CONTROLLERS = 'all_controllers';   //  表示所有控制器

    ALL_ACTIONS = 'all_actions';           //  表示所有控制器内的方法

    4、测试一下,创建一个testacl.php文件,

     1 <?php
     2 class Testacl extends Auth_Controller {
     3     function __construct() {
     4         parent::__construct();
     5     }
     6     
     7     function index() {
     8         echo "index method";
     9     }
    10     
    11     function add() {
    12         echo "添加页,只有管理员和编辑有权限操作";
    13     }
    14 }

    运行结果:在MY_Controller中我们假设了role=“gm”,

         所以访问http://localhost/CodeIgniter_2.1.1/index.php?c=testacl&m=index时输出 "index method"

          而访问:http://localhost/CodeIgniter_2.1.1/index.php?c=testacl&m=add时输出 “无权限”。

  • 相关阅读:
    康托(逆)展开(2015.8.6)
    高精度计算(2015.8.1)
    笔记(2015.8.1)
    筛法求素数(2015.7.30)
    欧几里德算法(2015.7.28)
    快速幂取模(2015.7.29)
    同余
    图论相关算法
    笔记(2015-07-24)
    ACM进阶计划
  • 原文地址:https://www.cnblogs.com/wuheping/p/2971424.html
Copyright © 2020-2023  润新知