繁体   English   中英

如何设计基于分层角色的访问控制系统

[英]How to design a hierarchical role based access control system

基本的交易是,我们为我们的项目定制了“kickstart”。 为此我们正在考虑重做用户控件。 我知道有很多关于一般rbac的问题,但我在层次结构rbac上找不到任何问题?

我们的要求是:

  • 可以将角色分配给组权限
  • 如果角色没有权限条目,则会自动拒绝该角色
  • 可以为用户授予覆盖权限
  • 用户覆盖权限是授予或拒绝
  • 如果明确拒绝用户权限,无论哪个角色说“已授予”,则覆盖获胜。
  • 用户可以拥有多个角色
  • 角色可以有层次结构
  • 角色可以继承其他角色(例如,“论坛超级版主”角色是“论坛版主”,“系统维护者”,“论坛版主”角色已经从“论坛用户”角色继承)
  • 从其他拒绝或授予权限的角色继承的角色会覆盖其子权限
  • 权限按“模块”分组(例如,“博客”模块可以具有“编辑条目”权限,“论坛”模块可以具有“编辑条目”权限,并且它们不会发生冲突)
  • 有“Everything and Anything”权限可自动授予完全访问权限

所以,有了这些要求,这就是我在考虑这样做的方式。

表:用户

id            | int     | unique id

表:角色

id            | int     | unique id
--------------|---------------------------------------------
title         | varchar | human readable name

表:权限

id            | int     | unique id
--------------|---------------------------------------------
module        | varchar | module name
--------------|---------------------------------------------
title         | varchar | human readable name
--------------|---------------------------------------------
key           | varchar | key name used in functions

表:Role_User

role_id       | int     | id from roles table
--------------|---------------------------------------------
user_id       | int     | id from users table

表:Permission_Role

id            | int     | unique id
--------------|---------------------------------------------
permission_id | int     | id from permissions table
--------------|---------------------------------------------
role_id       | int     | id from roles table
--------------|---------------------------------------------
grant         | tinyint | 0 = deny, 1 = grant

表:Permission_User

id            | int     | unique id
--------------|---------------------------------------------
permission_id | int     | id from permissions table
--------------|---------------------------------------------
user_id       | int     | id from users table
--------------|---------------------------------------------
grant         | tinyint | 0 = deny, 1 = grant

嗯,实际上这是它的一半,我确信这一部分,我要坚持的部分是层级角色。

那么,我该如何设计呢? 我的想法是,为了节省数据库查询,我将在登录时构建权限矩阵并将其保存到会话中,因此查询不必太简单,因为它们仅针对每次登录运行一次。

我看到的问题是,我将需要知道角色的层次结构,以便在解析继承之前​​解析继承的角色权限。

用户权限是简单的部分,每用户权限基本上是最终解析的组。

有一种方法可以通过对表Roles使用递归关系来实现角色继承,方法是对另一条记录进行角色引用:

1:n继承

此关系将在Roles记录中添加1 : n继承。 您可以使用此存储函数获取整个层次结构树:

CREATE FUNCTION `getHierarchy`(`aRole` BIGINT UNSIGNED)
RETURNS VARCHAR(1024)
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE `aResult` VARCHAR(1024) DEFAULT NULL;
DECLARE `aParent` BIGINT UNSIGNED;

SET `aParent` = (SELECT `parent` FROM `Roles` WHERE `id` = `aRole`);

WHILE NOT `aParent` IS NULL DO

    SET `aResult` = CONCAT_WS(',', `aResult`, `aParent`);
    SET `aParent` = (SELECT `parent` FROM `Roles` WHERE `id` = `aParent`);

END WHILE;

RETURN IFNULL(`aResult`, '');
END

然后,您可以使用以下内容获取所有已授予的权限:

SELECT
    `permission_id`
FROM
    `Permission_Role`
WHERE
    FIND_IN_SET(`role_id`, `getHierarchy`({$role}))
    AND
    grant;

如果还不够,那么你可以做另一个继承表:

n:m继承

但是,在这种情况下,需要另一种层次结构获取算法。


要解决覆盖问题,您必须获得角色权限和用户权限。 然后,将user权限写入session roles权限。


另外,我建议删除Permission_RolePermission_User中的grant列。 无需为每个权限映射每个权限。 足以使用EXISTS查询:如果有记录,则授予权限,否则 - 不是。 如果需要检索所有权限和状态,可以使用LEFT JOIN

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM