我正在尝试实现RBAC,但一个用户可以拥有多个角色,每个角色都在特定的上下文下。
上下文基于三个因素,即Company
、Product
和Region
。
因此,用户A可以是公司1的Admin
,也可以是公司2>产品3>区域4 的Viewer
建立这种RBAC的最佳方法是什么?
我目前正在手动滚动这一点,因此正在寻找构建DB表的最佳方式,以实现这种级别的细粒度访问。
不幸的是,这是在一个运行PHP CodeIgniter/mySQL的遗留应用程序上,所以任何现代的现有库都可能不兼容。
更新
到目前为止我有这个。Permissions
表映射到Roles
,然后将Roles
分配给用户,并给定上下文。
account_id | role_id | company_id | product_id | region_id |
------------------------------------------------------------
1 | 1 | | | |
2 | 2 | 1 | | |
2 | 3 | 2 | 1 | |
3 | 4 | 3 | 1 | 2 |
3 | 4 | 3 | 1 | 3 |
3 | 4 | 3 | 1 | 4 |
这个的SQL看起来有点像。。。
SELECT DISTINCT account_id
FROM user_roles ur, role_permissions rp
JOIN permissions p ON rp.permission_id=p.id
WHERE (
#correct user that has a role with the permission we want
ur.account_id = 1
AND rp.permission_id IN (1,2,3)
AND ur.role_id = rp.role_id
#if the user is sys admin they can see everything
AND (
ur.role_id = 1
#if the user is company admin
OR ( ur.role_id = 2 AND ur.company_id=@cid )
#if the user is product admin
OR ( ur.role_id = 3 AND ur.company_id=@cid AND ur.product_id=@pid )
#if the user is any other role then the need explicit access
OR ( ur.role_id > 3 AND ur.company_id=@cid AND ur.product_id=@pid AND ur.country_code=@cc )
)
);
这是有效的,但我相信一定有更好的方法。
下一个问题是如何将层次结构应用于角色
所以公司>产品>地区的"管理员"只能创建其角色或更低级别的用户?
我必须在我们所处的上下文中查找他们分配的角色,然后返回每个级别低于用户级别的角色?
这个上下文可以更好地作为字符串放置吗1.3.gb'/'1.2'?然后在查找角色时,我首先形成上下文字符串?
用户表可以交叉引用卷表,每个卷都有一个特定的角色标识号,带有can_write
、can_read
列(等等)
你的传家宝可能看起来像这样:
Users:
uid(int) auto_increment primary
role_id(int)
Roles:
rid(int) auto_increment primary
description(varchar)
// any access values ie: can_read(int)
然后,您可以设置一个子角色表,允许查看区域。
访问这些表的一些示例代码:
$stmp = (new PDO(...))->Prepare("SELECT role_id FROM Users WHERE uid = :userid");
$stmp->bindValue(":userid", $id); // I'd suggest storing a login key using sessions
$stmp->execute();
$user_permissions = $stmp->Fetch()['role_id'];
// Reference the Roles table for permission lists
$stmp = (new PDO(...))->Prepare("SELECT * FROM Roles WHERE rid = :roleid");
$stmp->bindValue(":roleid", $user_permissions);
[...]
希望这能有所帮助。