欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  php教程

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

程序员文章站 2024-01-14 13:32:22
...
官方的权限系统太复杂了,初学者往往云里雾里,搞不清楚。
这是本人的傻瓜版改造。请各位品鉴。
官方的rbac。本人看了诸多文章,虽然最后搞明白了,但是耗费的脑细胞的确不少。而且要数据库支持。用起来实在不便于和自己的系统集成。好坏暂且不论,单从繁琐上而言,的确不算完美。
自己琢磨了一个傻瓜版,简单说一下吧。欢迎拍砖。
权限系统的原理就不详细解说了。总之要点就这几个:
1.用户表,记录具体操作人员账号。
userid
username
2.角色表,或者叫用户组表。记录系统可以使用的角色。
roleid
rolename
funstr(关键)
其中有一个字段:权限串funstr。要用varchar(2000)或更大,是个大字符字段,存储角色的具体权限点信息。下面会解释怎么用。
3.用户角色关联表。把用户和角色关联起来。
再次基础上有无数变形。再此就不在说了,基本就是这三个。
ok,帽子戏法开始:
有看官会问;权限表呢?缺少记录系统权限点的表啊。
这就是傻瓜版的要点,
新建一个类,暂起名fun吧。
其中建一个array,保存系统的所有module的所有class的所有function。
就是系统的所有操作方法。这个array是这样的:class AdmFunarrAction extends Action
{

/////////////////////////////////////////////////////////////////////////////
/////////////////////////网站所有功能的array/////////////////////////////////

//主键:GROUP-class-function用于权限检查时定位
//值为另一个array,存储具体对应function功能的相关信息

//1.id--权限点对应的字符编码(字母开头,后跟两位字母和数字)
// 是进行权限检查的依据

//2.pid--父权限点对应的字符编码,构造权限树时使用

//3.n--name--权限点名称

//4.t--tree--是否用来构造树节点,存入权限串中
//值1--构造树节点,存入权限串。
//值0--不用构造树节点,不存入权限串,只用来检查,
// 处理几个fun合并用一个id的情况,比如各种查询合并成一个id

//5.l--login--是否需要登录,强行控制,保证安全,0--无需登录 1--必须登录

//6.x--xx--权限点详细说明

//7.p--pic --权限点的树形图标
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//-----总后台所有模块的权限数组
PUBLIC $admfunarr = array(
// 主键 | 标号 |父级标号 |名称 |节点属性| 强制登陆|详细 |图标
'aaaa-0000-0000' =>array('id'=>'a','pid'=>'aaaa', 'n'=>'总后台', 't'=>'1','l'=>'0','x' => '总后台根节点','p'=>'icon-add'),
'Admin-Main-index' =>array('id'=>'a01','pid'=>'a', 'n'=>'后台登陆页', 't'=>'1','l'=>'0','x' => '机构后台管理的登陆页面','p'=>'icon-add'),
'Admin-Main-main' =>array('id'=>'a02','pid'=>'a', 'n'=>'后台首页', 't'=>'1','l'=>'1','x' => '机构后台管理的主页面','p'=>'icon-add'),
'aaaa-0000-0001' =>array('id'=>'a03','pid'=>'a02', 'n'=>'基础设置', 't'=>'1','l'=>'1','x' => '基础设置菜单','p'=>'icon-add'),
'Admin-Adminuser-index' =>array('id'=>'a04','pid'=>'a03', 'n'=>'管理员维护', 't'=>'1','l'=>'1','x' => '管理员维护,包括增删改查','p'=>'icon-add'),
'Admin-Adminuser-getlist' =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员列表', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'Admin-Adminuser-getone' =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员单个查询', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'Admin-Adminuser-addfun' =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员新增', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'Admin-Adminuser-updatefun' =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员修改', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'Admin-Adminuser-delfun' =>array('id'=>'a04','pid'=>'a04', 'n'=>'合-管理员删除', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'aaaa-0000-0002' =>array('id'=>'a05','pid'=>'a02', 'n'=>'高级设置', 't'=>'1','l'=>'1','x' => '基础设置菜单','p'=>'icon-add'),
'Admin-Corp-index' =>array('id'=>'a06','pid'=>'a05', 'n'=>'高级管理员维护', 't'=>'1','l'=>'1','x' => '管理员维护,包括增删改查','p'=>'icon-add'),
'Admin-Adminuser-getlist1' =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员列表', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'Admin-Adminuser-getone1' =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员单个查询', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'Admin-Adminuser-addfun1' =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员新增', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'Admin-Adminuser-updatefun1' =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员修改', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),
'Admin-Adminuser-delfun1' =>array('id'=>'a06','pid'=>'a06', 'n'=>'合-管理员删除', 't'=>'0','l'=>'1','x' => '总后台管理员管理','p'=>'icon-add'),





);
这是一个复合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方法,你的其他类都从这里继承吧。 /*
* 总后台公共模块的基础类
*/
class AdminCommonAction extends Action{
/*
* 初始化
* 权限验证
* Session判断
*/
public function _initialize(){

header ( 'Content-Type:text/html;charset=utf-8' );
//是否登录判断,没有登录需要登录
if (!session('?admuserid')){
redirect(__APP__.'/'.GROUP_NAME.'/Login/index');
}
//获得session权限串
$funstr='';
if (session('?admuserfunstr')){
$funstr=session('admuserfunstr');
}
//判断当前访问是否在权限串中
//1.获得权限数组,我的权限数组在一个专门类中,所以要在这里调用一下,也可以写在一起,完全无压力。
$s=new AdmFunarrAction();
$admfunarr=$s->admfunarr;//权限数组
//2.根据group,action,fun获得key
$key=GROUP_NAME.'-'.MODULE_NAME.'-'.ACTION_NAME;//注意加‘-’啊。用‘-’进行连接
if (!array_key_exists("$key",$admfunarr)){
if (! IS_AJAX) {
header ( 'Content-Type:text/html;charset=utf-8' );
echo ('

失败555...!你可能没有权限啊,快升级吧...

-------------------------返回');
exit ();
} else {
$json = '{"zt":0,"xx":"失败555...!你可能没有权限啊,快升级吧..."}';
echo $json;
exit ();
}
}
//3.根据key获得id
$id=$admfunarr["$key"]['id'];
//4.根据id判断是否在权限字符串中
$pos = strpos($funstr,$id);
if (!$pos){
if (! IS_AJAX) {
header ( 'Content-Type:text/html;charset=utf-8' );
echo ('

失败555555...!你可能没有权限啊,快升级吧...

-------------------------返回');
exit ();
} else {
$json = '{"zt":0,"xx":"失败555555...!你可能没有权限啊,快升级吧..."}';
echo $json;
exit ();
}
}

}

}
有了代码,其实没什么好说的了,唠叨一句:
.根据group,action,fun获得key,这三个tp都有常量的,获得了key,根据key找到系统功能array的对应值,从里面提取出id,
然后判断这个id在不在角色表的funstr串当中就可以判定是否可以操作了。

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


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





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