Thinkphp3.2.3中的RBAC权限验证

来源:互联网 发布:下载个淘宝 编辑:程序博客网 时间:2024/05/20 14:25
最近在用TP的RBAC权限控制,在这里记录学习一下。先来看看相关的概念

一、相关概念

访问控制与RBAC模型
1、访问控制:
        通常的多用户系统都会涉及到访问控制,所谓访问控制,是指通过某种方式允许活限制用户访问能力及范围的一种方法。这主要是由于系统需要对关键资源进行保护,防止由于非法入侵或者误操作对业务系统造成破坏。简而言之,访问控制即哪些用户可以访问哪些资源。
        一般而言,访问控制系统包括三个组成部分:
        主体:发出访问请求的实体,通常指用户或者用户进程。
        客体:被保护的资源,通常是程序,数据,文件或者设备。
        访问策略:主体和客体的映射规则,确定一个主体是否对客体具有访问能力。

2、RBAC (Role-Base-Access-Controll)
        基于角色的访问控制(RBAC)的概念在七十年代就已经提出,但是直到九十年代由于安全需求的发展才又引起了广泛关注。RBAC 的核心思想是将系统资源的访问权限进行分类或者建立层次关系,抽象为角色的概念,然后根据安全策略将用户和角色关联,从而实现了用户和权限之间的对照。RBAC 通过引入角色并将其作为权限管理的中介,将访问控制系统分为两个部分,即权限与角色的关联和角色与用户的关联,具有灵活易控制的优点。
来源:http://www.ibm.com/developerworks/cn/java/j-lo-rbacwebsecurity/

我的理解就是给用户赋予不同的角色,给角色服务不同的权限,权限可以看成要访问资源的集合,角色只是用户和权限的过渡层,可能会问为什要有一个角色过渡层,可以试想一下没有role过渡层,有多个用户有着相同的数个权限,分配管理权限的时候,要重复分配权限,工作量很大,更何况修改权限的时候,更麻烦,可以说不利于代码的维护,所以要有一个role的过渡层。下面来看看TP(thinkphp)中的RBAC的实现及用法。

二、TP中的RBAC类及使用RBAC类
1、RBAC权限验证的大致流程:
        ①、验证当前操作是否需要验证
        ②、验证是否登录
        ③、查看当前用户的身份
        ④、获取当前用户的权限列表
        ⑤、进行权限验证

2、RBAC所依赖的5张数据表
[sql] view plain copy
print?
  1. CREATE TABLE IF NOT EXISTS `think_access` (  
  2.   `role_id` smallint(6) unsigned NOT NULL,  
  3.   `node_id` smallint(6) unsigned NOT NULL,  
  4.   `level` tinyint(1) NOT NULL,  
  5.   `module` varchar(50) DEFAULT NULL,  
  6.   KEY `groupId` (`role_id`),  
  7.   KEY `nodeId` (`node_id`)  
  8. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;  
  9.    
  10. CREATE TABLE IF NOT EXISTS `think_node` (  
  11.   `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,  
  12.   `namevarchar(20) NOT NULL,  
  13.   `title` varchar(50) DEFAULT NULL,  
  14.   `status` tinyint(1) DEFAULT '0',  
  15.   `remark` varchar(255) DEFAULT NULL,  
  16.   `sort` smallint(6) unsigned DEFAULT NULL,  
  17.   `pid` smallint(6) unsigned NOT NULL,  
  18.   `level` tinyint(1) unsigned NOT NULL,  
  19.   PRIMARY KEY (`id`),  
  20.   KEY `level` (`level`),  
  21.   KEY `pid` (`pid`),  
  22.   KEY `status` (`status`),  
  23.   KEY `name` (`name`)  
  24. ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;  
  25.    
  26. CREATE TABLE IF NOT EXISTS `think_role` (  
  27.   `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,  
  28.   `namevarchar(20) NOT NULL,  
  29.   `pid` smallint(6) DEFAULT NULL,  
  30.   `status` tinyint(1) unsigned DEFAULT NULL,  
  31.   `remark` varchar(255) DEFAULT NULL,  
  32.   PRIMARY KEY (`id`),  
  33.   KEY `pid` (`pid`),  
  34.   KEY `status` (`status`)  
  35. ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;  
  36.    
  37. CREATE TABLE IF NOT EXISTS `think_role_user` (  
  38.   `role_id` mediumint(9) unsigned DEFAULT NULL,  
  39.   `user_id` char(32) DEFAULT NULL,  
  40.   KEY `group_id` (`role_id`),  
  41.   KEY `user_id` (`user_id`)  
  42. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;  
  43.   
  44. CREATE TABLE `think_user` (  
  45.   `id` int(11) NOT NULL AUTO_INCREMENT,  
  46.   `namevarchar(20) DEFAULT '',  
  47.   `passwordvarchar(25) NOT NULL,  
  48.   `phone_num` varchar(20) DEFAULT NULL,  
  49.   `register_time` int(11) DEFAULT NULL,  
  50.   `login_time` int(11) DEFAULT NULL,  
  51.   `login_ip` varchar(20) DEFAULT NULL,  
  52.   `status` tinyint(1) DEFAULT NULL,  
  53.   PRIMARY KEY (`id`)  
  54. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;  

数据表模型如下:

这五张表的关系如下:
一个用户对应着多个角色;一个角色可以属于对个用户;是多对多的关系,需要用个中间表即role_user表;
一个角色可以有多个权限;一个权限可以属于多个用户;是多对多的关系,需要有个中间表即access表;

那node表示什么?
node表是记录权限的表,说白了就是记录应用,控制器,及方法的表,即要访问资源的集合;比如要访问的Admin应用下的Index控制器下的index方法;从这里可以明确了TP的RBAC是控制用户对控制器及方法的访问权限进行权限的管理。下面来看个图,加深理解:


这张图里面的用户,角色,结点,权限及用户与角色中间表一一对应即可(这图是从网上盗的)。其实还可将用户进行抽象,对其进行分组,不同组别里面的角色不同,这可一根据不同的业务进行尝试。可以参考这篇博客
http://www.cnblogs.com/zwq194/archive/2011/03/07/1974821.html
知道了RBAC需要的5张数据表,下面来看看RBAC类是如何实现权限验证的。

3、RBAC类
RBAC类中三个核心的方法:
    ①getAccessList()获取权限列表
[php] view plain copy
print?
  1. static public function getAccessList($authId) {  
  2.         // Db方式权限数据  
  3.         $db     =   Db::getInstance(C('RBAC_DB_DSN'));  
  4.         $table = array('role'=>C('RBAC_ROLE_TABLE'),'user'=>C('RBAC_USER_TABLE'),'access'=>C('RBAC_ACCESS_TABLE'),'node'=>C('RBAC_NODE_TABLE'));  
  5.         $sql    =   "select node.id,node.name from ".  
  6.                     $table['role']." as role,".  
  7.                     $table['user']." as user,".  
  8.                     $table['access']." as access ,".  
  9.                     $table['node']." as node ".  
  10.                     "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and access.node_id=node.id and node.level=1 and node.status=1";  
  11.         $apps =   $db->query($sql);  
  12.         $access =  array();  
  13.         foreach($apps as $key=>$app) {  
  14.             $appId  =   $app['id'];  
  15.             $appName     =   $app['name'];  
  16.             // 读取项目的模块权限  
  17.             $access[strtoupper($appName)]   =  array();  
  18.             $sql    =   "select node.id,node.name from ".  
  19.                     $table['role']." as role,".  
  20.                     $table['user']." as user,".  
  21.                     $table['access']." as access ,".  
  22.                     $table['node']." as node ".  
  23.                     "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and access.node_id=node.id and node.level=2 and node.pid={$appId} and node.status=1";  
  24.             $modules =   $db->query($sql);  
  25.             // 判断是否存在公共模块的权限  
  26.             $publicAction  = array();  
  27.             foreach($modules as $key=>$module) {  
  28.                 $moduleId    =   $module['id'];  
  29.                 $moduleName = $module['name'];  
  30.                 if('PUBLIC'== strtoupper($moduleName)) {  
  31.                 $sql    =   "select node.id,node.name from ".  
  32.                     $table['role']." as role,".  
  33.                     $table['user']." as user,".  
  34.                     $table['access']." as access ,".  
  35.                     $table['node']." as node ".  
  36.                     "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and access.node_id=node.id and node.level=3 and node.pid={$moduleId} and node.status=1";  
  37.                     $rs =   $db->query($sql);  
  38.                     foreach ($rs as $a){  
  39.                         $publicAction[$a['name']]    =   $a['id'];  
  40.                     }  
  41.                     unset($modules[$key]);  
  42.                     break;  
  43.                 }  
  44.             }  
  45.             // 依次读取模块的操作权限  
  46.             foreach($modules as $key=>$module) {  
  47.                 $moduleId    =   $module['id'];  
  48.                 $moduleName = $module['name'];  
  49.                 $sql    =   "select node.id,node.name from ".  
  50.                     $table['role']." as role,".  
  51.                     $table['user']." as user,".  
  52.                     $table['access']." as access ,".  
  53.                     $table['node']." as node ".  
  54.                     "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id  or (access.role_id=role.pid and role.pid!=0 ) ) and role.status=1 and access.node_id=node.id and node.level=3 and node.pid={$moduleId} and node.status=1";  
  55.                 $rs =   $db->query($sql);  
  56.                 $action = array();  
  57.                 foreach ($rs as $a){  
  58.                     $action[$a['name']]  =   $a['id'];  
  59.                 }  
  60.                 // 和公共模块的操作权限合并  
  61.                 $action += $publicAction;  
  62.                 $access[strtoupper($appName)][strtoupper($moduleName)]   =  array_change_key_case($action,CASE_UPPER);  
  63.             }  
  64.         }  
  65.         return $access;  
  66.     }  

可以看出方法是依次获取项目模块,控制器,动作方法的权限的。

    ②saveAccessList()检测用户的权限列表,并将权限存储到SESSION中
[php] view plain copy
print?
  1. //用于检测用户权限的方法,并保存到Session中  
  2.     static function saveAccessList($authId=null) {  
  3.         if(null===$authId)   $authId = $_SESSION[C('USER_AUTH_KEY')];  
  4.         // 如果使用普通权限模式,保存当前用户的访问权限列表  
  5.         // 对管理员开发所有权限  
  6.         if(C('USER_AUTH_TYPE') !=2 && !$_SESSION[C('ADMIN_AUTH_KEY')] )  
  7.             $_SESSION['_ACCESS_LIST']   =   self::getAccessList($authId);  
  8.         return ;  
  9.     }  

    ③AccessDecision()权限决策,就是判断用户拥有哪些权限
[php] view plain copy
print?
  1. //权限认证的过滤器方法  
  2.     static public function AccessDecision($appName=MODULE_NAME) {  
  3.         //检查是否需要认证  
  4.         if(self::checkAccess()) {  
  5.             //存在认证识别号,则进行进一步的访问决策  
  6.             $accessGuid   =   md5($appName.CONTROLLER_NAME.ACTION_NAME);  
  7.             if(empty($_SESSION[C('ADMIN_AUTH_KEY')])) {  
  8.                 if(C('USER_AUTH_TYPE')==2) {  
  9.                     //加强验证和即时验证模式 更加安全 后台权限修改可以即时生效  
  10.                     //通过数据库进行访问检查  
  11.                     $accessList = self::getAccessList($_SESSION[C('USER_AUTH_KEY')]);  
  12.                 }else {  
  13.                     // 如果是管理员或者当前操作已经认证过,无需再次认证  
  14.                     if$_SESSION[$accessGuid]) {  
  15.                         return true;  
  16.                     }  
  17.                     //登录验证模式,比较登录后保存的权限访问列表  
  18.                     $accessList = $_SESSION['_ACCESS_LIST'];  
  19.                 }  
  20.                 //判断是否为组件化模式,如果是,验证其全模块名  
  21.                 if(!isset($accessList[strtoupper($appName)][strtoupper(CONTROLLER_NAME)][strtoupper(ACTION_NAME)])) {  
  22.                     $_SESSION[$accessGuid]  =   false;  
  23.                     return false;  
  24.                 }  
  25.                 else {  
  26.                     $_SESSION[$accessGuid]  =   true;  
  27.                 }  
  28.             }else{  
  29.                 //管理员无需认证  
  30.                 return true;  
  31.             }  
  32.         }  
  33.         return true;  
  34.     }  

从代码中可以看出,权限判断是有两种方式一种是根据session中的权限列表进行校验,一种是每次都查询数据库进行校验(下面配置参数说明的时候会说明)
[php] view plain copy
print?
  1. array(3) {  
  2.   ["phone"] => string(11) "18792455613"  
  3.   ["uid"] => string(2) "13"  
  4.   ["_ACCESS_LIST"] => array(1) {  
  5.     ["ADMIN"] => array(5) {  
  6.       ["ARTICLE"] => array(0) {  
  7.       }  
  8.       ["CATEGORY"] => array(3) {  
  9.         ["CATEGORYLIST"] => string(2) "15"  
  10.         ["ADDCATEGORY"] => string(2) "16"  
  11.         ["ALTERCATEGORY"] => string(2) "17"  
  12.       }  
  13.       ["MEDIA"] => array(2) {  
  14.         ["IMAGE"] => string(2) "12"  
  15.         ["VIDEO"] => string(2) "13"  
  16.       }  
  17.       ["INDEX"] => array(5) {  
  18.         ["USERLIST"] => string(1) "7"  
  19.         ["ADDUSER"] => string(1) "8"  
  20.         ["ADDROLE"] => string(1) "9"  
  21.         ["ADDNODE"] => string(2) "10"  
  22.         ["INDEX"] => string(2) "11"  
  23.       }  
  24.       ["DATA"] => array(0) {  
  25.       }  
  26.     }  
  27.   }  
  28. }  

AccessDecision()方法中调用checkAccess()方法进行验证模块的过滤即去除不需要验证的模块,控制器和方法。知道了RBAC的实现思路,下面来使用RBAC类进行权限验证。

4、使用RBAC类进行权限验证

①首先处理5张表,就是对5张表的增删该查

实现逻辑代码如下:建立一个RbacController.class.php的控制器
[php] view plain copy
print?
  1. /** 
  2.      * 角色列表视图 
  3.      */  
  4.     public function role(){  
  5.         $roleList = M("role")->select();  
  6.         $this->assign("roleList",$roleList);  
  7.         layout("base");  
  8.         $this->display();  
  9.     }  
  10.    
  11.     /** 
  12.      * 角色表单处理 
  13.      */  
  14.     public function roleHandle(){  
  15.         $id = I("get.id");  
  16.         if(M("role")->where(array("id"=>$id))->delete()){  
  17.             $this->success("删除成功",U("Admin/Index/role"));  
  18.         }else{  
  19.             $this->error("删除失败");  
  20.         }  
  21.     }  
  22.    
  23.     /** 
  24.      * 结点列表视图 
  25.      */  
  26.     public function node(){  
  27.         $field = array('id','name','title','pid');  
  28.         $node = M('node')->field($field)->order('sort')->select();  
  29.         $this->node = node_merge($node);  
  30.         layout("base");  
  31.         $this->display();  
  32.     }  
  33.    
  34.     /** 
  35.      * 权限列表视图 
  36.      */  
  37.     public function access(){  
  38.    
  39.         $rid = I('rid',0,"intval");  
  40.         $field = array('id','name','title','pid');  
  41.         $node = M('node')->order('sort')->field($field)->select();  
  42.         //原有的权限  
  43.         $access = M('access')->where(array('role_id'=>$rid))->getField('node_id',true);  
  44.    
  45.         $this->node = node_merge($node,$access);  
  46.         // dump($this->node);  
  47.         $this->rid = $rid;  
  48.         layout("base");  
  49.         $this->display();  
  50.     }  
  51.    
  52.     /** 
  53.      * 设置权限表单处理 
  54.      */  
  55.     public function setAccess(){  
  56.         $rid = I('rid',0,"intval");  
  57.         $db = M('access');  
  58.         $db->where(array('role_id'=>$rid))->delete();  
  59.         $data = array();  
  60.         foreach ($_POST['access'as $v ) {  
  61.             $tmp = explode('_'$v);  
  62.             $data[] = array(  
  63.                 'role_id' => $rid,  
  64.                 'node_id' => $tmp[0],  
  65.                 'level' => $tmp[1]  
  66.             );  
  67.         }  
  68.         if ($db->addAll($data)) {  
  69.             $this->success('修改成功',U('Admin/Index/role'));  
  70.         }else{  
  71.             $this->error('修改失败');  
  72.         }  
  73.    
  74.     }  
  75.    
  76.     /** 
  77.      * 添加角色视图 
  78.      */  
  79.     public function addRole(){  
  80.         layout("base");  
  81.         $this->display();  
  82.     }  
  83.    
  84.     /** 
  85.      * 添加角色表单处理 
  86.      */  
  87.     public function addRoleHandle(){  
  88.         $data = I("post.");  
  89.         if(M("role")->data($data)->add()){  
  90.             $this->success("添加成功",U("Admin/Index/role"));  
  91.         }else{  
  92.             $this->error("添加角色失败,请稍后再试");  
  93.         }  
  94.     }  
  95.    
  96.     /** 
  97.      * 添加结点视图 
  98.      */  
  99.     public function addNode(){  
  100.         $this->pid = I("pid",0,"intval");  
  101.         $this->level = I("level",1,"intval");  
  102.         switch ($this->level){  
  103.             case 1:  
  104.                 $this->type = "应用";  
  105.                 break;  
  106.             case 2:  
  107.                 $this->type = "控制器";  
  108.                 break;  
  109.             case 3:  
  110.                 $this->type = "方法";  
  111.                 break;  
  112.         }  
  113.         layout("base");  
  114.         $this->display();  
  115.     }  
  116.    
  117.     /** 
  118.      * 添加结点表单处理 
  119.      */  
  120.     public function addNodeHandle(){  
  121.         $data = I("post.");  
  122.         if(M("node")->data($data)->add()){  
  123.             $this->success("添加成功",U("Admin/Index/node"));  
  124.         }else{  
  125.             $this->error("添加失败,请稍后再试");  
  126.         }  
  127.     }  

其中有一个结点和权限整合的函数node_merge(),实现的思路是递归进行结点添加,将统一控制器中的不同方法整合在一起,代码如下:这段代码放在Common文件夹下的function.php里
[php] view plain copy
print?
  1. /** 
  2.  * 权限结点整合 
  3.  * @param  array   $node   结点数组 
  4.  * @param  array   $access 权限数组 
  5.  * @param  integer $pid    父级ID 
  6.  * @return array           组合后的数组 
  7.  */  
  8. function node_merge($node,$access=null,$pid=0){  
  9.     $arr = array();  
  10.     foreach($node as $v){  
  11.         if(is_array($access)){  
  12.             $v['access'] = in_array($v['id'],$access) ? 1 : 0;  
  13.         }  
  14.         if($pid==$v['pid']){  
  15.             $v['child'] = node_merge($node,$access,$v['id']);  
  16.             $arr[] = $v;  
  17.         }  
  18.     }  
  19.     return $arr;  
  20. }  

②完成了准备工作可以使用RBAC类了,首先先对RABC进行参数配置,下面是配置参数
[html] view plain copy
print?
  1. 配置文件增加设置  
  2. USER_AUTH_ON 是否需要认证  
  3. USER_AUTH_TYPE 认证类型 //1:代表着登录验证2:代表着试试验证  
  4. USER_AUTH_KEY 认证识别号  
  5. REQUIRE_AUTH_MODULE  需要认证模块  
  6. NOT_AUTH_MODULE 无需认证模块  
  7. USER_AUTH_GATEWAY 认证网关 //不是必须的  
  8. RBAC_DB_DSN  数据库连接DSN //不是必须的  
  9. RBAC_ROLE_TABLE 角色表名称  
  10. RBAC_USER_TABLE 用户表名称 //这里是用户和角色的中间表  
  11. RBAC_ACCESS_TABLE 权限表名称  
  12. RBAC_NODE_TABLE 节点表名称  

其中值得注意的是:下面四块
[php] view plain copy
print?
  1. USER_AUTH_GATEWAY 认证网关 //不是必须的  
  2. RBAC_DB_DSN  数据库连接DSN //不是必须的  
  3. RBAC_USER_TABLE 用户表名称 //这里是用户和角色的中间表  
  4. USER_AUTH_TYPE 认证类型 //1:代表着登录验证2:代表着试试验证  

时时验证是指不将权限信息存入session,而是每访问一个资源,查询数据库进行权限校验;
登录验证是指将权限信息存入session,而是每访问一个资源,根据session中的信息进行验证;
可以看出时时验证的安全性更高,但消耗的资源也多。可以看看上面AccessDecision的代码加深理解。

下面是配置文件的代码:
[php] view plain copy
print?
  1. <?php  
  2. return array(  
  3.     'RBAC_SUPERADMIN'=>'admin',  
  4.     'ADMIN_AUTH_KEY' =>'superAdmin'//超级管理员识别  
  5.     'USER_AUTH_ON' =>true,  //是否开启权限验证  
  6.     'USER_AUTH_TYPE' =>1,   //验证类型(1:登录时验证2:时时验证)  
  7.     'USER_AUTH_KEY' =>'uid'//用户验证识别号  
  8.     'NOT_AUTH_ACTION' =>'index'// 无需验证的动作方法  
  9.     'NOT_AUTH_MODULE' =>''//无需验证的控制器  
  10.     'RBAC_ROLE_TABLE' =>'think_role',//角色表名称  
  11.     'RBAC_USER_TABLE' => 'think_role_user',//用户与角色的中间表  
  12.     'RBAC_ACCESS_TABLE' =>'think_access',//权限表  
  13.     'RBAC_NODE_TABLE' =>'think_node',//节点表  
  14.     'URL_HTML_SUFFIX' =>'',  
  15.     // 'SHOW_PAGE_TRACE' => true,  
  16. );  

③开始“真正”使用RABC类进行权限验证
    阐述下我用到的两个类:
    LoginController.class.php处理用户登录请求;
    CommonController.class.php添加_initialize()函数,让其他控制器继承此类;这里值得说明的是_initialize()函数,他会在调用其他方法之前执行,这也就是为什么要在这个函数中进行权限验证;

  One: 使用登录验证方式:首先在登录的时候向session中写入权限LoginController.class.php
[php] view plain copy
print?
  1. <?php  
  2. /** 
  3.  * Created by PhpStorm. 
  4.  * User: zhangpeng 
  5.  * Date: 2016/1/29 
  6.  * Time: 12:37 
  7.  */  
  8.    
  9. namespace Admin\Controller;  
  10.    
  11. use Org\Util\Rbac;  
  12. use Think\Controller;  
  13.    
  14. class LoginController extends Controller  
  15. {  
  16.     /** 
  17.      * 登录首页视图 
  18.      */  
  19.     public function index()  
  20.     {  
  21.         $this->display();  
  22.     }  
  23.    
  24.     /** 
  25.      * 登录表单处理 
  26.      */  
  27.     public function loginHandle()  
  28.     {  
  29.         if (IS_POST) {  
  30.             $userModel = M('user');  
  31.             $where = array(  
  32.                 'phone_num' => I('post.phone_num'),  
  33.                 'password' => md5(I('post.password'))  
  34.             );  
  35.             $result = $userModel->where($where)->find();  
  36.             if (!$result) {  
  37.                 $this->error("登陆失败");  
  38.             }else{  
  39.                 session("phone",I('post.phone_num'));  
  40.                 session("uid",$result['id']);  
  41.    
  42.                 if($result['name']==C('RBAC_SUPERADMIN')){  
  43.                     session(C('ADMIN_AUTH_KEY'),true);  
  44.                 }  
  45.    
  46.                 //将权限写入session  
  47.                 Rbac::saveAccessList();  
  48.                 $this->success('欢迎登陆',U('Admin/Index/index'));  
  49.             }  
  50.         }  
  51.     }  
  52.    
  53.     /** 
  54.      * 登出操作 
  55.      */  
  56.     public function logout(){  
  57.         if(session("phone")){  
  58.             session("uid",null);  
  59.             session("phone",null);  
  60.             session(null);  
  61.         }  
  62.         $this->redirect("Login/index");  
  63.     }  
  64. }  



其次,在_initialize()函数中进行权限验证:CommonController.class.php
[php] view plain copy
print?
  1. <?php  
  2. /** 
  3.  * Created by PhpStorm. 
  4.  * User: zhangpeng 
  5.  * Date: 2016/2/1 
  6.  * Time: 23:28 
  7.  */  
  8.    
  9. namespace Admin\Controller;  
  10.    
  11.    
  12. use Org\Util\Rbac;  
  13. use Think\Controller;  
  14.    
  15. /** 
  16.  * Class CommonController 
  17.  * @package Admin\Controller 
  18.  * 用户验证用户的状态,实现用户页面保留的功能 
  19.  */  
  20. class CommonController extends Controller  
  21. {  
  22.     /** 
  23.      * 自动执行函数,tp中自带 
  24.      */  
  25.     public function _initialize(){  
  26.         if(!session("uid")){  
  27.             $this->redirect('Login/index');  
  28.         }  
  29.    
  30.         if(C('USER_AUTH_ON')){  
  31.             Rbac::AccessDecision()||$this->error("你没有权限");  
  32.         }  
  33.     }  
  34. }  

Two:时时验证,只需要在_initialize()函数中添加验证即可,代码不在赘述。

其中值得注意的是,我用的是TP3.2.3,此时TP支持命名空间和类自动加载机制,所以不像老版本需要用import引入RBAC类才能使用。

三、总结
RBAC类短短的200多行代码实现了权限控制的需求,感觉十分厉害。后续把我的demo代码上传,与大家一起学习。




原创粉丝点击