跳转到主要内容

带域(Domain)的 RBAC

带域的角色定义​

在 Casbin 中,角色可以是 按域划分(domain-scoped) 的:同一个用户在不同的域(租户)中可以拥有不同的角色。这很适合多租户和云系统这类一个用户在多个租户中工作的场景。

使用包含 三个 元素的角色定义;第三个元素就是域:

[role_definition]
g = _, _, _

第三个字段是域。示例策略:

p, admin, tenant1, data1, read
p, admin, tenant2, data2, read

g, alice, admin, tenant1
g, alice, user, tenant2

于是:tenant1 中的 admin 可以读取 data1。Alice 在 tenant1 中是 admin、在 tenant2 中是 user;她可以读取 data1,但不能读取 data2(只有 tenant2 中的 admin 才能读取 data2)。

Matcher:把域加进 g 并要求它匹配:

[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act

自定义域的名称​

按惯例域被命名为 dom,但你可以在 request 和 policy 定义中使用任何名称(tenant、workspace 等):

[request_definition]
r = sub, tenant, obj, act

[policy_definition]
p = sub, tenant, obj, act

[role_definition]
g = _, _, _

[matchers]
m = g(r.sub, p.sub, r.tenant) && r.tenant == p.tenant && r.obj == p.obj && r.act == p.act

如果对域使用模式匹配(例如 keyMatch),只要域在 request 和 policy 中都位于索引 1 处,Casbin 就会自动从模型中推断出域的名称:

[matchers]
m = g(r.sub, p.sub, r.tenant) && keyMatch(r.tenant, p.tenant) && r.obj == p.obj && r.act == p.act

如果要用 自定义 的域名称或位置的域相关 API(例如 GetAllUsersByDomain()),请在创建 enforcer 之后设置其索引。完整示例:rbac_with_domains_model.conf。

域的名称与位置

域通常命名为 dom,并放在第二位(sub, dom, obj, act)。在 Go Casbin 中你可以使用其他名称或位置;此时应在初始化之后调用 e.SetFieldIndex("p", constant.DomainIndex, index),这样 GetAllUsersByDomain() 之类的 API 才能正常工作。

# Using `domain` instead of `dom`
[policy_definition]
p = sub, obj, act, domain
e.SetFieldIndex("p", constant.DomainIndex, 3) // index starts from 0
users := e.GetAllUsersByDomain("domain1") // without SetFieldIndex, this will raise an error