phpcms中的RBAC权限系统

Posted 诗里刻画的影子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了phpcms中的RBAC权限系统相关的知识,希望对你有一定的参考价值。

原文链接:https://www.cnblogs.com/duanbiaowu/p/5089243.html

PHPCMS中的RBAC权限系统主要用到了4张数据表:管理员表,角色表,菜单表,菜单权限表。先来看看数据库的数据表结构:

admin 管理员表

ID字段类型Null默认索引额外注释
1 userid mediumint(6) unsigned   PK auto_increment 用户id
2 username varchar(20) YES   INDEX   用户名
3 password varchar(32) YES       密码
4 roleid smallint(5) YES 0     角色
5 encrypt varchar(6) YES       加密因子
6 lastloginip varchar(15) YES       最后登录ip
7 lastlogintime int(10) unsigned YES 0     最后登录时间
8 email varchar(40) YES       Email
9 realname varchar(50) NO       真实姓名
10 card varchar(255) NO       密保卡

admin_role 角色表

ID字段类型Null默认索引额外注释
1 roleid tinyint(3) unsigned     PK auto_increment 角色id
2 rolename varchar(50) NO       角色名称
3 description text NO       描述
4 listorder smallint(5) unsigned NO 0 INDEX   排序
5 disabled tinyint(1) unsigned NO 0 INDEX   状态:1,禁用
ID字段类型Null默认索引额外注释
1 id smallint(6) unsigned     PK auto_increment 菜单id
2 name char(40) NO       名称
3 parentid smallint(6) NO 0 INDEX   父id
4 m char(20) NO   INDEX   m
5 c char(20) NO   INDEX   c
6 a char(20) NO   INDEX   a
7 data char(100) NO       附件参数
8 listorder smallint(6) unsigned NO 0 INDEX   排序
9 display enum(\'1\',\'0\') NO 1     是否显示,1 显示

admin_role_priv 菜单权限表

ID字段类型Null默认索引额外注释
1 roleid tinyint(3) unsigned   0 PK   角色id
2 m char(20) NO   INDEX   m
3 c char(20) NO   INDEX   c
4 a char(20) NO   INDEX   a
5 data char(30) NO       附件属性
6 siteid smallint(5) unsigned NO 0 INDEX   所属站点

下面来简单分析一下4张表的关系:

1.用户表中的每个用户有一个角色字段roleid,表明了该用户属于哪个角色。
2.角色表的主键为roleid,与用户表中的roleid相对应,还有角色名称,描述等,比如phpCMS系统默认有超级管理员、总编、发布人员等角色。
3.管理员权限表中主键也是roleid,与角色表中的主键roleid相对应,表明了该角色拥有的后台操作权限。字段m、c、a分别代表的是模型 | 控制器 | 方法,因为PHPCMS本身也是MVC结构,所以更好地使权限系统的粒度细化到方法上面。
4.菜单表主要存放菜单属性,其中的m、c、a与管理员权限表中的字段相对应。

最后来看看用户的操作及验证流程:

首先,用户在后台登录,如果登录成功,将roleid(角色id)存入SESSION,然后跳转到后台首页,在PHPCMS系统中,整个后台操作的部分都在admin模块中,所以该模块中所有的控制器均继承自admin类,并且在构造方法中执行了父类的构造方法(admin的构造方法)。那么,admin类的构造方法有执行了哪些操作呢?

首先是调用自身的 check_admin() 来判断用户是否登录,紧接着判断用户的权限: check_priv()

check_priv() 方法源代码:

## 格式略微修改
final public function check_priv()
{
    if (ROUTE_M == \'admin\' && ROUTE_C == \'index\' && in_array(ROUTE_A, array(\'login\', \'init\', \'public_card\'))) {
        return true;
    }
    if ($_SESSION[\'roleid\'] == 1) {
        return true;
    }

    $siteid = param::get_cookie(\'siteid\');
    $action = ROUTE_A;
    $privdb = pc_base::load_model(\'admin_role_priv_model\');

    if (preg_match(\'/^public_/\', ROUTE_A)) {
        return true;
    }
    if (preg_match(\'/^ajax_([a-z]+)_/\', ROUTE_A, $_match)) {
        $action = $_match[1];
    }

    $r = $privdb->get_one(
        array(
            \'m\' => ROUTE_M, 
            \'c\' => ROUTE_C, 
            \'a\' => $action, 
            \'roleid\' => $_SESSION[\'roleid\'], 
            \'siteid\' => $siteid
        )
    );
    if (!$r) {
        showmessage(\'您没有权限操作该项\', \'blank\');
    }
}

该方法首先判断当前正在进行的操作,如果是登录或者初始化操作,则退出。
然后判断角色是否为超级管理员(超级管理员默认为最高权限),如果是,依旧退出,或者如果当前方法为公开的(没有权限限制),同样退出。
最后加载 admin_role_priv_model,也就是管理员权限模型,获取当前要操作的模型 | 控制器 | 方法,利用 admin_role_priv_model 提供的方法进行查询,如果可以返回数据,则说明角色可以进行当前操作,反之,弹出提示信息:您没有权限操作该项,然后退出!

对了,忘了介绍后台菜单的生成过程啦!其实用到的还是admin类自身的方法:admin_menu(): 不过该方法是在 index.tpl.php 模板中调用的,主要进行的操作是先取出菜单表中所有菜单,然后判断当前角色,如果为超级管理员,则直接返回菜单数组,反之,则将符合当前角色权限的菜单数组返回。

以上是关于phpcms中的RBAC权限系统的主要内容,如果未能解决你的问题,请参考以下文章

RBAC权限管理

RBAC从入门到精通

Git@OSC —— Anycmd,RBAC 权限管理框架小编已经被这个 logo 鄙视了,不知道你有没有被代码牛逼到~

聊一个 GitHub 上开源的 RBAC 权限管理系统,很6!

20181104 tp中的权限(RBAC)

Yii2全面解析之权限管理RBAC