优先级模型
Casbin 可以给 policy 设置优先级:当多条 policy 同时匹配时,优先级最高的一条生效(其结果可以是 allow 也可以是 deny)。
隐式优先级(按 policy 顺序)
policy 的顺序决定优先级:列表中排在最前面的优先级最高。使用如下 effect:
[policy_effect]
e = priority(p.eft) || deny
显式优先级(数字字段)
在 policy 中增加一个 priority 字段;数字越小代表优先级越高。非数字的值会被视为最低优先级。参见 casbin#550。
自定义 priority 字段
默认的 priority 字段名是 priority。如果你想用别的名字(例如 customized_priority),需要在初始化后调用 e.SetFieldIndex("p", constant.PriorityIndex, index) 并重新加载 policy。示例:TestCustomizedFieldIndex。
在 policy 中使用显式优先级的示例:
[policy_definition]
p = customized_priority, sub, obj, act, eft
Golang 代码示例:
e, _ := NewEnforcer("./example/priority_model_explicit_customized.conf",
"./example/priority_policy_explicit_customized.csv")
// Due to the customized priority token, the enforcer fails to handle the priority.
ok, err := e.Enforce("bob", "data2", "read") // the result will be `true, nil`
// Set PriorityIndex and reload
e.SetFieldIndex("p", constant.PriorityIndex, 0)
err := e.LoadPolicy()
if err != nil {
log.Fatalf("LoadPolicy: %v", err)
}
ok, err := e.Enforce("bob", "data2", "read") // the result will be `false, nil`
:::
只有 AddPolicy 和 AddPolicies 会遵循显式优先级。请不要通过 UpdatePolicy 修改 priority 字段。
完整的模型:
[request_definition]
r = sub, obj, act
[policy_definition]
p = priority, sub, obj, act, eft
[role_definition]
g = _, _
[policy_effect]
e = priority(p.eft) || deny
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
policy.csv
p, 10, data1_deny_group, data1, read, deny
p, 10, data1_deny_group, data1, write, deny
p, 10, data2_allow_group, data2, read, allow
p, 10, data2_allow_group, data2, write, allow
p, 1, alice, data1, write, allow
p, 1, alice, data1, read, allow
p, 1, bob, data2, read, deny
g, bob, data2_allow_group
g, alice, data1_deny_group
请求:
alice, data1, write --> true // because `p, 1, alice, data1, write, allow` has the highest priority
bob, data2, read --> false
bob, data2, write --> true // because bob has the role of `data2_allow_group` which has the right to write data2, and there's no deny policy with higher priority
主体优先级(角色/用户层级)
使用 subjectPriority(p.eft),让优先级来自角色层级:叶子节点(例如最终用户)的优先级高于内部角色。该层级必须是树,不能是图;如果一个用户拥有多个角色,这些角色在每棵树中应当处于相同的深度。同一层级的平局按 policy 顺序决定。参见 casbin#833、casbin#831。
模型:
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act, eft
[role_definition]
g = _, _
[policy_effect]
e = subjectPriority(p.eft) || deny
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
policy.csv
p, root, data1, read, deny
p, admin, data1, read, deny
p, editor, data1, read, deny
p, subscriber, data1, read, deny
p, jane, data1, read, allow
p, alice, data1, read, allow
g, admin, root
g, editor, admin
g, subscriber, admin
g, jane, editor
g, alice, subscriber
请求:
jane, data1, read --> true // because jane is at the bottom, her priority is higher than that of editor, admin, and root
alice, data1, read --> true
角色层级结构:
role: root
└─ role: admin
├─ role editor
│ └─ user: jane
│
└─ role: subscriber
└─ user: alice
自动优先级分配:
role: root # auto priority: 30
└─ role: admin # auto priority: 20
├─ role: editor # auto priority: 10
└─ role: subscriber # auto priority: 10