我正在使用Yii RBAC来控制用户对我的应用程序的访问,它包含三个mySql表;
authitem
(RBAC角色项目)
authitemchild
(任何属于其他角色的RBAC规则)
authitemassignment
(为用户分配角色)
例如,我们可能有这样的表:
authitem:
| 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
)
完全适用于上面的例子,但我只是扩展了应用程序,为儿童提供了多个级别,即
authitem:
| 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(),......等等,这可能有助于抓取我需要的数据
答案 0 :(得分: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
)