# RBAC
## 角色定义
`[role_definition]`是RBAC角色继承关系的定义。 Casbin 支持 RBAC 系统的多个实例, 例如, 用户可以具有角色及其继承关系, 资源也可以具有角色及其继承关系。 这两个 RBAC 系统不会互相干扰。
此部分是可选的。 如果在模型中不使用 RBAC 角色, 则省略此部分。
~~~ini
[role_definition]
g = _, _
g2 = _, _
~~~
上述角色定义表明,`g`是一个 RBAC系统,`g2`是另一个 RBAC 系统。`_, _`表示角色继承关系的前项和后项,即前项继承后项角色的权限。 一般来讲,如果您需要进行角色和用户的绑定,直接使用`g`即可。 当您需要表示角色(或者组)与用户和资源的绑定关系时,可以使用`g`和`g2`这样的表现形式。 请参见[rbac\_model](https://github.com/casbin/casbin/blob/master/examples/rbac_model.conf)和[rbac\_model\_with\_resource\_roles](https://github.com/casbin/casbin/blob/master/examples/rbac_with_resource_roles_model.conf)的示例。
在Casbin里,我们以policy表示中实际的用户角色映射关系 (或是资源-角色映射关系),例如:
~~~
p, data2_admin, data2, read
g, alice, data2_admin
~~~
这意味着`alice`是角色`data2_admin`的一个成员。`alice`在这里可以是用户、资源或角色。 Cabin 只是将其识别为一个字符串。
接下来在matcher中,应该像下面的例子一样检查角色信息:
~~~ini
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
~~~
它表示请求中的`sub`应该在策略中定义了`sub`角色。
有几个注意事项:
1. Casbin 只存储用户角色的映射关系。
2. Cabin 没有验证用户是否是有效的用户,或者角色是一个有效的角色。 这应该通过认证来解决。
3. RBAC 系统中的用户名称和角色名称不应相同。因为Casbin将用户名和角色识别为字符串, 所以当前语境下Casbin无法得出这个字面量到底指代用户`alice`还是角色`alice`。 这时,使用明确的`role_alice`,问题便可迎刃而解。
4. 假设`A`具有角色`B`,`B`具有角色`C`,并且`A`有角色`C`。 这种传递性在当前版本会造成死循环。
## 角色层次
Casbin 的 RBAC 支持 RBAC1 的角色层次结构功能,如果`alice`具有`role1`,`role1`具有`role2`,则`alice`也将拥有`role2`并继承其权限。
下面是一个称为层次结构级别的概念。 因此, 此示例的层次结构级别为2。 对于Casbin中的内置角色管理器, 可以指定最大层次结构级别。 默认值为10。 这意味着终端用户`alice`只能继承10个级别的角色。
~~~go
// NewRoleManager is the constructor for creating an instance of the
// default RoleManager implementation.
func NewRoleManager(maxHierarchyLevel int) rbac.RoleManager {
rm := RoleManager{}
rm.allRoles = &sync.Map{}
rm.maxHierarchyLevel = maxHierarchyLevel
rm.hasPattern = false
return &rm
}
~~~
## 如何区分用户和角色?
在RBAC中,Casbin不对用户和角色进行区分。 它们都被视为字符串。 如果你只使用单层的RBAC模型(角色不会成为另一个角色的成员)。 可以使用`e.GetAllSubjects()`获取所有用户,`e.GetAllRoles()`获取所有角色。 它们会为规则`g, u, r`分别列出所有的`u`和`r`。
但在使用多层RBAC模型时(带有角色继承),你的应用不会记录一个名字(字符串)是用户还是角色,或者用户和角色有相同的名字。 可以给角色加上像`role::admin`的前缀再传递到Casbin中。 由此可以通过查看前缀来区分用户和角色。
## 如何查询隐性角色或权限?
当用户通过RBAC层次结构继承角色或权限,而不是直接在策略规则中分配它们时,我们将这种类型的分配称为`implicit`。 要查询这种隐式关系,需要使用以下两个api:`GetImplicitRolesForUser()`以及`GetImplicitPermissionsForUser`替代`GetRolesForUser()`以及`GetPermissionsForUser`. 有关详情,请参阅[this GitHub issue](https://github.com/casbin/casbin/issues/137)。
## 在 RBAC 中使用模式匹配
有时,您希望将具有特定模式的某些subjects(或objects)自动授予某个角色。 RBAC中的模式匹配函数可以帮助做到这一点。 模式匹配函数与前一个函数共享相同的参数和返回值:[matcher function](https://casbin.org/docs/en/syntax-for-models#functions-in-matchers)。
我们知道RBAC在matcher中通常表示为`g(r.sub, p.sub)`。 然后我们将使用以下策略:
~~~
p, alice, book_group, read
g, /book/1, book_group
g, /book/2, book_group
~~~
所以`alice`可以读所有的book,包括`book 1`和`book 2`。 但是可能有成千上万个book,使用`g`策略规则将每一个book添加到book角色(或组)是非常单调乏味的。
但是使用模式匹配函数,您可以只用一行代码编写策略:
~~~
g, /book/:id, book_group
~~~
Casbin会自动将`/book/1`和`/book/2`匹配成模式`/book/:id`。 您只需要向强制程序注册该功能,如:
~~~go
e.rm.(*defaultrolemanager.RoleManager).AddMatchingFunc("KeyMatch2", util.KeyMatch2)
~~~
您可以在这里看到完整的示例 :[here](https://github.com/casbin/casbin/blob/dbdb6cbe2e7a80863e4951f9ff36da07fef01b75/model_test.go#L278-L307)。
it's notable that:
1. 只有`g`种的第一参数 (aka 用户) 支持模式函数。 您正在使用第三个参数(domain),目前不支持。
## 角色管理器
角色管理器用于管理Casbin中的RBAC角色层次结构(用户角色映射)。 角色管理器可以从Casbin策略规则或外部源(如LDAP、Okta、Auth0、Azure AD等)检索角色数据。 我们支持角色管理器的不同实现。 为了保持代码轻量级,我们没有把角色管理器代码放在主库中(默认的角色管理器除外)。 下面提供了Casbin角色管理器的完整列表。 欢迎任何第三方对角色manager进行新的贡献,如果有请告知我们,我们将把它放在这个列表中:)
| 角色管理器 | 作者 | 描述 |
| --- | --- | --- |
| [Default Role Manager (built-in)](https://github.com/casbin/casbin/blob/master/rbac/default-role-manager/role_manager.go) | Casbin | 支持存储在Casbin策略中的角色层次结构 |
| [Session Role Manager](https://github.com/casbin/session-role-manager) | [EDOMO Systems](https://github.com/edomosystems) | 支持存储在Casbin策略中的角色层次结构,以及基于时间范围的会话 |
| [Okta Role Manager](https://github.com/casbin/okta-role-manager) | Casbin | 支持存储在[Okta](https://www.okta.com/)中的角色层次结构 |
| [Auth0 Role Manager](https://github.com/casbin/auth0-role-manager) | Casbin | 支持存储在[Auth0](https://auth0.com/)'s[Authorization Extension](https://auth0.com/docs/extensions/authorization-extension/v2)授权扩展名中的角色层次结构 |
对于开发人员:所有角色manager必须实现[RoleManager](https://github.com/casbin/casbin/blob/master/rbac/role_manager.go)接口。[Session Role Manager](https://github.com/casbin/session-role-manager)可以用作参考实现。