RBAC
角色定义
[role_definition] 部分定义 RBAC 的角色(继承)关系。Casbin 可以同时运行多 个 RBAC 系统:一个用于用户(带角色继承),还可以额外有一个用于资源。二者相互独立。
这一部分是可选的;如果你不使用 RBAC,可以省略它。
[role_definition]
g = _, _
g2 = _, _
这里的 g 和 g2 是两个角色系统;_, _ 表示每个系统都有两侧(例如用户和角色)。只用 g 表示用户角色;当资源也有角色时再加上 g2。示例:rbac_model.conf、rbac_with_resource_roles_model.conf。
用户—角色(以及资源—角色)的映射关系存储在 policy 中,例如:
p, data2_admin, data2, read
g, alice, data2_admin
因此 alice 拥有角色 data2_admin。Casbin 把所有名称都当作字符串处理(用户、资源或角色)。
在 matcher 中使用角色:
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
因此,只有当请求主体拥有 policy 中给出的角色时,请求才会被允许。
- Casbin 只存储和评估用户—角色(以及资源—角色)的映射关系;它不会校验用户或角色是否真实存在。那是认证的职责。
- 不要给用户和角色使用相同的名字(例如用户
alice和角色alice),因为 Casbin 无法区分它们。必要时请使用前缀(例如role_alice)。 - 角色继承是传递且不限层级的:如果 A 拥有角色 B,B 拥有角色 C, 那么 A 实际上就拥有角色 C。
policy 中的 subject 通常命名为 sub 并排在第一列。在 Go Casbin 中你可以使用其他名字和顺序;但之后必须在创建 enforcer 之后调用 e.SetFieldIndex("p", constant.SubjectIndex, index),这样 DeleteUser 之类的 API 才能使用正确的列。
# `subject` here is for sub
[policy_definition]
p = obj, act, subject
e.SetFieldIndex("p", constant.SubjectIndex, 2) // index starts from 0
ok, err := e.DeleteUser("alice") // without SetFieldIndex, it will raise an error
角色层级
Casbin 实现了 RBAC1 式的角色层级:如果 alice 拥有 role1,且 role1 拥有 role2,那么 alice 实际上就拥有 role2 及其权限。
层级深度指的是你允许的继承层数。默认的角色管理器最大深度为 10(可配置),因此一个用户最多可以继承 10 层角色。
// 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
}
区分用户与角色
在 Casbin 中,用户和角色都是字符串。在扁平 RBAC(没有角色层级)中,GetAllSubjects() 和 GetAllRoles() 返回 g 规则的左右两侧(通常是用户和角色)。而在有层级的情况下,同一个名字可能既作为用户又作为角色出现;如果你的应用不去区分它们,请使用命名约定(例如前缀 role::),并在解读结果时加以检查。
隐式角色与权限
通过层级继承而来的角色和权限(不仅是直接分配的那些)称为隐式的。使用 GetImplicitRolesForUser() 和 GetImplicitPermissionsForUser() 可以把它们包含进来;GetRolesForUser() 和 GetPermissionsForUser() 只返回直接分配的结果。参见 GitHub #137。
RBAC 中的模式匹配
参见 带模式的 RBAC。
角色管理器
自定义角色管理请参见角色管理器。