Rumah  >  Artikel  >  php教程  >  一个字段解决RBAC权限。RBAC傻瓜版改造。

一个字段解决RBAC权限。RBAC傻瓜版改造。

WBOY
WBOYasal
2016-06-07 11:44:231126semak imbas

官方的权限系统太复杂了,初学者往往云里雾里,搞不清楚。
这是本人的傻瓜版改造。请各位品鉴。
官方的rbac。本人看了诸多文章,虽然最后搞明白了,但是耗费的脑细胞的确不少。而且要数据库支持。用起来实在不便于和自己的系统集成。好坏暂且不论,单从繁琐上而言,的确不算完美。
自己琢磨了一个傻瓜版,简单说一下吧。欢迎拍砖。
权限系统的原理就不详细解说了。总之要点就这几个:
1.用户表,记录具体操作人员账号。
userid
username
2.角色表,或者叫用户组表。记录系统可以使用的角色。
roleid
rolename
funstr(关键)
其中有一个字段:权限串funstr。要用varchar(2000)或更大,是个大字符字段,存储角色的具体权限点信息。下面会解释怎么用。
3.用户角色关联表。把用户和角色关联起来。
再次基础上有无数变形。再此就不在说了,基本就是这三个。
ok,帽子戏法开始:
有看官会问;权限表呢?缺少记录系统权限点的表啊。
这就是傻瓜版的要点,
新建一个类,暂起名fun吧。
其中建一个array,保存系统的所有module的所有class的所有function。
就是系统的所有操作方法。这个array是这样的:class AdmFunarrAction extends Action<br> {<br>     <br>     /////////////////////////////////////////////////////////////////////////////<br>     /////////////////////////网站所有功能的array/////////////////////////////////  <br>  <br>    //主键:GROUP-class-function用于权限检查时定位<br>    //值为另一个array,存储具体对应function功能的相关信息<br>      <br>      //1.id--权限点对应的字符编码(字母开头,后跟两位字母和数字)<br>      //     是进行权限检查的依据<br> <br>      //2.pid--父权限点对应的字符编码,构造权限树时使用  <br> <br>      //3.n--name--权限点名称 <br> <br>      //4.t--tree--是否用来构造树节点,存入权限串中<br>      //值1--构造树节点,存入权限串。     <br>      //值0--不用构造树节点,不存入权限串,只用来检查,<br>      //     处理几个fun合并用一个id的情况,比如各种查询合并成一个id  <br>   <br>      //5.l--login--是否需要登录,强行控制,保证安全,0--无需登录 1--必须登录<br>      <br>      //6.x--xx--权限点详细说明      <br>      <br>      //7.p--pic --权限点的树形图标 <br>     /////////////////////////////////////////////////////////////////////////////<br>     /////////////////////////////////////////////////////////////////////////////    <br>   //-----总后台所有模块的权限数组<br>     PUBLIC $admfunarr = array(<br> //     主键                            |        标号      |父级标号     |名称                         |节点属性| 强制登陆|详细                          |图标             <br> 'aaaa-0000-0000'                      =>array('id'=>'a','pid'=>'aaaa',  'n'=>'总后台',                  't'=>'1','l'=>'0','x' => '总后台根节点','p'=>'icon-add'),<br> 'Admin-Main-index'                    =>array('id'=>'a01','pid'=>'a',   'n'=>'后台登陆页',              't'=>'1','l'=>'0','x' => '机构后台管理的登陆页面','p'=>'icon-add'),<br> 'Admin-Main-main'                     =>array('id'=>'a02','pid'=>'a',   'n'=>'后台首页',                't'=>'1','l'=>'1','x' => '机构后台管理的主页面','p'=>'icon-add'),                         <br>   'aaaa-0000-0001'                      =>array('id'=>'a03','pid'=>'a02', 'n'=>'基础设置',              't'=>'1','l'=>'1','x' => '基础设置菜单','p'=>'icon-add'),      <br>     'Admin-Adminuser-index'               =>array('id'=>'a04','pid'=>'a03', 'n'=>'管理员维护',          't'=>'1','l'=>'1','x' => '管理员维护,包括增删改查','p'=>'icon-add'),       <br>       'Admin-Adminuser-getlist'             =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员列表',     't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>       'Admin-Adminuser-getone'              =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员单个查询', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>       'Admin-Adminuser-addfun'              =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员新增',     't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>       'Admin-Adminuser-updatefun'           =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员修改',     't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>       'Admin-Adminuser-delfun'              =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员删除',     't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>   'aaaa-0000-0002'                      =>array('id'=>'a05','pid'=>'a02', 'n'=>'高级设置',              't'=>'1','l'=>'1','x' => '基础设置菜单','p'=>'icon-add'),      <br>     'Admin-Corp-index'               =>array('id'=>'a06','pid'=>'a05', 'n'=>'高级管理员维护',      't'=>'1','l'=>'1','x' => '管理员维护,包括增删改查','p'=>'icon-add'),       <br>       'Admin-Adminuser-getlist1'             =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员列表',     't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>       'Admin-Adminuser-getone1'              =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员单个查询', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>       'Admin-Adminuser-addfun1'              =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员新增',     't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>       'Admin-Adminuser-updatefun1'           =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员修改',     't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),       <br>       'Admin-Adminuser-delfun1'              =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员删除',     't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),                       <br>         <br>         <br>         <br>         <br>         <br>         );   这是一个复合array,array的每一项也都是一个array。
array的主键是GROUP-class-function三个合成的。别说你不知道这三个的意思啊。
每个主键对应的值也是一个array,描述这个主键对应的function。有这么几个:
//1.id--权限点对应的字符编码,比如a01,a02之类
(字母开头,后跟两位字母和数字,可以重复)
这个是关键啊看条件需要时可以重复前面角色表权限字段(funstr)里面保存的就是用逗号分隔的这个funciton编码组合,
代表了这个角色可以拥有的全部操作。 是进行权限检查的依据!

------由于我是用ztree进行权限管理,下面这些附加属性只是为了构造ztree需要的json便于前台分配权限时操作。
除了name(功能的名称)必须,你完全可以忽略不用。但其中仍有精妙之处,请大家耐心。
//2.pid--父权限点对应的字符编码,构造权限树时使用(ztree需要,没什么好说的)

//3.n--name--权限点名称 (没什么好说的。你的function干什么用的总要起个名字吧)

//4.t--tree--是否用来构造树节点,存入权限串中(这个精妙了
//值1--构造树节点,存入权限串。
//值0--不用构造树节点,不存入权限串,只用来检查, 处理几个fun合并用一个id的情况,比如一个针对用户的增删改查合并成一个功能点id。
------这什么意思???
我们前面说了,每个function都要在这个数组中有一条记录。但是不是每个function
都代表一个功能点。有的时候权限控制比较粗,比如我只需要控制一个用户管理权限,有这个权限就可以进行用户的增删改查
的全部操作,不需要再细分增删改查这四个操作权限。这时就可以把增删改查的四个权限合并,设置一个虚拟的权限点,比如
上面的 'aaaa-0000-0001',他下面增加增删改查的方法,但是都用同一个编码。这就是编码重复的条件
这样,再检查权限时,就当做一个权限点进行检查了。一个权限点代表增删改查四个具体操作。
精妙吧.....呵呵呵,无耻!


//5.l--login--是否需要登录,硬编码强行控制,保证安全,即便无意误分派了权限,比如给游客分派了登录才能有的权限,
在这里也可以挡一下。0--无需登录 1--必须登录

//6.x--xx--权限点详细说明 (没什么说了)

//7.p--pic --权限点的树形图标 (没什么说了,ztree需要)


---------------------------------以上权限array解释完毕,如头晕,请移步草榴开心一下再来
一个字段解决RBAC权限。RBAC傻瓜版改造。

有了这个你的系统的全部function的array,还需要权限点表吗?
而且,维护这样一个array,比维护一个权限点的表,不知道容易了多少倍。

接下来的权限判断就是老生长谈了,无非建一个基类,写一个init方法,你的其他类都从这里继承吧。<?php <br /> /*<br>  * 总后台公共模块的基础类<br>  */<br> class AdminCommonAction extends Action{<br>     /*<br>      * 初始化<br>      * 权限验证<br>      * Session判断<br>      */<br>     public function _initialize(){<br> <br>       header ( 'Content-Type:text/html;charset=utf-8' );<br>         //是否登录判断,没有登录需要登录<br>         if (!session('?admuserid')){<br>                redirect(__APP__.'/'.GROUP_NAME.'/Login/index'); <br>             }<br>         //获得session权限串<br>         $funstr='';<br>         if (session('?admuserfunstr')){<br>               $funstr=session('admuserfunstr');<br>             } <br>         //判断当前访问是否在权限串中<br>           //1.获得权限数组,我的权限数组在一个专门类中,所以要在这里调用一下,也可以写在一起,完全无压力。<br>             $s=new AdmFunarrAction();<br>             $admfunarr=$s->admfunarr;//权限数组            <br>           //2.根据group,action,fun获得key<br>             $key=GROUP_NAME.'-'.MODULE_NAME.'-'.ACTION_NAME;//注意加‘-’啊。用‘-’进行连接<br>             if (!array_key_exists("$key",$admfunarr)){<br>                 if (! IS_AJAX) {<br>                     header ( 'Content-Type:text/html;charset=utf-8' );<br>                     echo ('<h2>失败555...!你可能没有权限啊,快升级吧...</h2>-------------------------<a>返回</a>');<br>                     exit ();<br>                 } else {<br>                     $json = '{"zt":0,"xx":"失败555...!你可能没有权限啊,快升级吧..."}';<br>                     echo $json;<br>                     exit ();<br>                 }              <br>             }<br>           //3.根据key获得id   <br>             $id=$admfunarr["$key"]['id'];<br>           //4.根据id判断是否在权限字符串中<br>             $pos = strpos($funstr,$id);<br>             if (!$pos){<br>                 if (! IS_AJAX) {<br>                     header ( 'Content-Type:text/html;charset=utf-8' );<br>                     echo ('<h2>失败555555...!你可能没有权限啊,快升级吧...</h2>-------------------------<a>返回</a>');<br>                     exit ();<br>                 } else {<br>                     $json = '{"zt":0,"xx":"失败555555...!你可能没有权限啊,快升级吧..."}';<br>                     echo $json;<br>                     exit ();<br>                 }                <br>             }    <br>          <br>     }<br>     <br> } 有了代码,其实没什么好说的了,唠叨一句:
.根据group,action,fun获得key,这三个tp都有常量的,获得了key,根据key找到系统功能array的对应值,从里面提取出id,
然后判断这个id在不在角色表的funstr串当中就可以判定是否可以操作了。

还少了一块,吧系统功能array的每个key对应的值中的id存入角色表的funstr当中。这个就不献丑了。随后有时间附上源代码吧。


周末闲来无事。小文一篇,蜻蜓点水而已,只是说个思路。欢迎各路大神拍啊拍啊拍!!!





AD:真正免费,域名+虚机+企业邮箱=0元

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn