基于角色的访问控制(RBAC)与上下文?

4
我正在尝试实现基于角色的访问控制(RBAC),但是一个用户可以拥有多个角色,并且每个角色都处于特定的上下文中。
上下文基于3个因素:公司、产品和地区。
因此,用户A可以是公司1的管理员,并且还可以是公司2 > 产品3 > 地区4的查看者。
针对这种RBAC设置,最佳方法是什么?
目前我正在手动编写代码 - 因此寻找最佳的数据库表结构方式,以允许这种粒度级别的访问。
不幸的是,这是一个使用PHP CodeIgniter / mySQL运行的遗留应用程序 - 因此任何现代的现有库可能不兼容。
更新:到目前为止,我已经创建了“权限”表,它映射到“角色”,然后将“角色”分配给用户,并赋予其上下文。
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”?然后在查找角色时,我首先形成上下文字符串?
1个回答

0

用户表可以与角色表进行交叉引用,每个角色都有一个特定的角色标识号,具有can_writecan_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);
[...]

希望这有所帮助。

谢谢Kyle,这与我目前想到的类似 - 目前我唯一遇到的问题是如何在这些上下文中建立角色层次结构。我会更新我的问题并提供更多信息。 - Matt Bryson
嗨,Kyle,我已经在问题中添加了更多信息,任何指针/建议都将不胜感激 - 我在这个问题上一直打转! - Matt Bryson
抱歉 @MattBryson,我对 SQL 不太擅长 - 我会点赞这个问题,以便有人能够给您更好的帮助。不过,我认为您可能过于依赖设置,您可以使用简单的 PHP 代码实现大部分功能。 - Jaquarh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接