# 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)可以用作參考實現。