1

我正在使用 Yii RBAC 来控制用户对我的应用程序的访问,它由三个 mySql 表组成;

authitem(RBAC 角色项)

authitemchild(属于其他角色的任何 RBAC 规则)

authitemassignment(为用户分配角色)

例如,我们可能有这样的表:

授权:

|   name (pk)   |
 areaASuperUser
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

authitemchild

|   parent (pk)   |   child (pk)   |
 areaASuperUser    areaACreateOnly
 areaASuperUser    areaAReadOnly
 areaASuperUser    areaAUpdateOnly
 areaASuperUser    areaADeleteOnly

 areaBSuperUser    areaBCreateOnly
 areaBSuperUser    areaBReadOnly
 areaBSuperUser    areaBUpdateOnly
 areaBSuperUser    areaBDeleteOnly

auithitemassignment

|    itemname (pk)   |   userid (pk)   |
 areaASuperUser       1

在上述场景中,id 为 1 的用户在 areaA 中具有完整的 CRUD 访问权限。我需要的是用户无权访问的所有角色的列表,我还需要考虑他们也有权访问的任何角色的子级。

我可以轻松获取用户无权访问的所有角色:

SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `authassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE  `aa`.`itemname` IS NULL

但这会返回:

 |   name    |
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

而且因为所有 areaA* 角色都是 areaASuperUser 的孩子,所以我不希望它们返回。

任何建议或推动正确方向将不胜感激!

*编辑:

谢谢@SuVeRa,你的回答:

SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `authassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE  
`aa`.`itemname` IS NULL 
AND `ai`.`name` NOT IN (
    SELECT
    `aic`.`child` itemname
    FROM `authitemchild` `aic`
    JOIN `authassignment` `aa`
    ON `aa`.`itemname` = `aic`.`parent`
    WHERE `aa`.`userid` = 1
)

非常适合上面的示例,但是我刚刚扩展了应用程序以包含多个儿童级别,即

授权:

|   name (pk)   |

 areaABSuperUser

 areaASuperUser
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBSuperUser
 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly

authitemchild

|   parent (pk)   |   child (pk)   |
 areaABSuperUser   areaASuperUser
 areaABSuperUser   areaBSuperUser

 areaASuperUser    areaACreateOnly
 areaASuperUser    areaAReadOnly
 areaASuperUser    areaAUpdateOnly
 areaASuperUser    areaADeleteOnly

 areaBSuperUser    areaBCreateOnly
 areaBSuperUser    areaBReadOnly
 areaBSuperUser    areaBUpdateOnly
 areaBSuperUser    areaBDeleteOnly

 areaCSuperUser    areaCCreateOnly
 areaCSuperUser    areaCReadOnly
 areaCSuperUser    areaCUpdateOnly
 areaCSuperUser    areaCDeleteOnly

auithitemassignment

|    itemname (pk)   |   userid (pk)   |
 areaABSuperUser      1

原来的答案会回来;

 |   name    |
 areaACreateOnly
 areaAReadOnly
 areaAUpdateOnly
 areaADeleteOnly

 areaBCreateOnly
 areaBReadOnly
 areaBUpdateOnly
 areaBDeleteOnly

 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly

因为它过滤掉了父母和孩子,而不是孩子的孩子。我追求的结果(在第二个例子中)是:

 |   name    |
 areaCSuperUser
 areaCCreateOnly
 areaCReadOnly
 areaCUpdateOnly
 areaCDeleteOnly

***编辑2:

专门针对 Yii:

我对 Yii 做了更多的阅读,CAuthManager有许多有用的方法,包括hasItemChild()isAssigned()getItemChildren()等,它们可以帮助抓取我需要的数据

4

1 回答 1

1

此查询可能对您有所帮助

SELECT DISTINCT `ai`.`name`
FROM `authitem` `ai`
LEFT JOIN `auithitemassignment` `aa`
ON `aa`.`itemname` = `ai`.`name` AND `aa`.`userid` = 1
WHERE  
`aa`.`itemname` IS NULL 
AND `ai`.`name` NOT IN (
    SELECT
    `aic`.`child` itemname
    FROM `authitemchild` `aic`
    JOIN `auithitemassignment` `aa`
    ON `aa`.`itemname` = `aic`.`parent`
    WHERE `aa`.`userid` = 1
)
于 2012-09-18T11:00:19.993 回答