利用 PHP-Casbin 中的优先级模型来做权限控制


优先级模型,所谓优先级,是指按一定的顺序加载策略。

优先级高的策略先加载,先加载的策略具有较高的优先级。

PHP-Casbin 目前支持三种模式:隐式优先顺序加载策略、显示优先顺序加载策略、基于角色和用户的层级关系加载策略。

优先级模式的配置在model.conf中的policy_effect中配置。

隐式优先顺序加载策略

隐式优先级模型配置在官方仓库的 examples 目录下 priority_model.conf文件中有示例,对应的策略文件为priority_policy.csv。具体的 model 配置请看下面的解释。

[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

可以看到policy_effect部分的配置为:e = priority(p.eft) || deny,在策略定义policy_definition部分最后一个参数有个eft决定参数,意思是在所有命中的策略中,策略的eft(p.eft)参数的值如果为明确结果(allow 或 deny)就作为决策结果,否则就以拒绝(deny)为决策结果。p.eft有三种取值:allowdenyindeterminate

显示优先顺序加载策

参考官方文档Load Policy with Explicit Priority

Currently, explicit priority only supports AddPolicy & AddPolicies. If UpdatePolicy has been called, you shouldn’t change the priority attribute.

文档中有这么一句话,就是目前只支持添加策略和批量添加策略。如果是修改策略则不能修改策略的优先级。

配置在官方仓库的 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

这个配置相比隐式优先顺序加载策略,只是在policy_definition中加了一个priority字段。就是在策略中用一个数值字段来代表优先级。看一下它的策略:

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字段从小到大升序。所以如果要指定策略的优先级只需要设置priority字段的数值即可。

基于角色和用户的层级关系加载策略

顾名思义,用户和角色、角色和角色都有可能有一个继承关系,甚至是多层级关系,那么这些关系会形成一个树形的层级,根据这个层级关系来加载策略,从而实现策略的优先级。

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 

policy_effect的配置为: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

虽然jane所属的角色editordata1read是拒绝的(deny),并且位置靠前,但jane本身有一条对data1read的允许allow策略,即便位置靠后,janedata1read 仍然为 allow。因为jane位于层级的最底层,具有较高的优先级。

角色的层级关系像这样:

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

所以在基于角色和用户的层级关系加载策略的模式下,最底层优先级最高,最顶层优先级最低

最后

在使用Casbin做权限控制时,有了这些优先级模式的加持,让 Casbin 可以更灵活的应对各种各样的需求。

特别是在各种工作流/工单审批时,不同的用户有不同或相同的审批权限,可以做出不同的审批结果,当多人审批意见出现冲突时,那么就可以通过优先级来决定最终审批结果,谁的优先级高按谁的审批结果。

原文:tech1024.com/original/3061

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!