在 Casbin 权限控制里,真正麻烦的往往不是“有没有规则”,而是“多条规则同时命中时到底按哪条算”。PHP-Casbin 提供的优先级模型,就是用来解决这类冲突决策问题:有的按加载顺序,有的按显式数值,有的按用户与角色的层级关系。看完这三种模式的配置方式、判定逻辑和示例结果,你就能判断当前业务更适合哪一种优先级策略。
为什么 Casbin 需要优先级模型
所谓优先级,本质上就是策略按照一定顺序参与决策。优先级高的策略先被考虑,命中后就更可能成为最终结果。
PHP-Casbin 目前支持三种模式:
- 隐式优先顺序加载策略
- 显式优先顺序加载策略
- 基于角色和用户层级关系加载策略
这些优先级模式的关键配置都写在 model.conf 的 policy_effect 中。也就是说,真正决定“多条策略冲突时如何裁决”的,不只是策略本身,还有策略效果的计算方式。
隐式优先:按策略加载顺序决定结果
隐式优先级模型在官方仓库 examples 目录下的 priority_model.conf 中有示例,对应策略文件为 priority_policy.csv。它的核心思路很直接:谁先加载,谁的优先级更高。

[request_definition]
r = sub, obj, act
[policy_definition]
p = 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
这里最关键的是这行配置:
e = priority(p.eft) || deny
它的含义是:如果命中的策略里,某条策略的 p.eft 给出了明确结论,就按这个明确结论执行;如果没有得到明确结论,默认按 deny 处理。
在这个模型里,p.eft 有三种取值:
allowdenyindeterminate
因此,隐式优先模型适合那些已经能稳定控制策略加载顺序的场景。它不需要额外字段,配置简单,但前提是你必须清楚策略文件或持久层加载时的先后顺序,否则排查冲突时不够直观。
显式优先:用 priority 字段直接声明高低
如果你不想把优先级隐藏在“谁先加载”这件事里,可以改用显式优先模型。官方文档对应的是 Load Policy with Explicit Priority。
Currently, explicit priority only supports AddPolicy & AddPolicies. If UpdatePolicy has been called, you shouldn't change the priority attribute.
这句话的意思很重要:目前显式优先只支持 AddPolicy 和 AddPolicies。如果你通过 UpdatePolicy 修改策略,就不应该同时修改优先级属性。
对应示例配置在官方仓库 examples 目录下的 priority_model_explicit.conf,策略文件为 priority_policy_explicit.csv。
[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
和隐式优先相比,这里只多了一个字段:
p = priority, sub, obj, act, eft
也就是把优先级从“隐含在顺序里”改成“直接写在策略字段里”。示例策略如下:
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
从这个例子可以直接看出规则:priority 数值越小,优先级越高。Casbin 会按 priority 字段从小到大升序排序,所以 1 会先于 10 生效。
这类模式特别适合规则量较多、冲突关系复杂、需要人工直观看出“谁压过谁”的业务。相比隐式顺序,它的优势在于可读性和可维护性更强;但代价是你需要额外维护一个优先级字段,并遵守官方对更新策略的限制。
主体层级优先:按用户与角色继承关系裁决
第三种模式和前两种不一样,它不再单纯看顺序,也不要求你手工填一个数字,而是根据用户和角色之间的继承层级来推导优先级。

这种场景通常出现在组织角色比较复杂的系统里:用户属于某个角色,角色又继承上层角色,甚至会形成多层树状结构。此时,策略冲突的裁决就可以交给层级关系本身。
subject_priority_model.conf 配置如下:
[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
这里的重点是:
e = subjectPriority(p.eft) || deny
subjectPriority 表示根据主体 sub 的层级来决定优先级。对应的策略文件 subject_priority_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
这里最容易让人误判的地方在于:虽然 editor 对 data1 的 read 是 deny,而且策略位置也靠前,但 jane 自己有一条 allow。最终结果仍然是 allow,原因不是文件里谁写在前面,而是 jane 位于层级最底层,优先级高于 editor、admin 和 root。
角色层级关系大致如下:
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
因此,在这种模式下可以总结成一句话:越靠近树的底层,优先级越高;越靠近顶层,优先级越低。
它很适合组织型权限、审批链、岗位继承这类天然存在上下级关系的系统。相比显式优先,它减少了手工维护数值的成本;但前提是你的角色继承关系本身足够清晰,否则最终决策会变得难以解释。
三种优先级模式该怎么选
如果你的规则冲突不多,策略来源单一,而且能稳定控制加载顺序,隐式优先已经够用,配置也最轻。
如果业务里经常出现“个人规则覆盖角色规则”“某条拒绝必须压过一批允许”这类明确冲突,显式优先会更合适,因为它能直接通过 priority 数值表达裁决顺序,排查起来也更直观。
如果你的权限结构本身依赖组织树、角色树、审批链或岗位继承,那么主体层级优先通常更贴近业务模型。它把“谁级别更具体、谁离实际用户更近”这件事直接纳入决策。
在实际项目中,Casbin 的这些优先级模式尤其适合工作流、工单审批和多人协作决策场景。不同用户可能拥有相同的操作权限,却给出相反的审批结果;这时系统就不能只看“是否命中策略”,还要进一步判断“谁的结论优先”。优先级模型的价值,正是在冲突发生时给出稳定、可解释的最终裁决。









