在使用casbin之前,要理解他的model

  • PERM元模型
  • 单商户模型
  • 多商户模型

PERM元模型


1
2
3
4
5
6
7
8
9
10
11
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act, (eft)

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
  • P [policy_definition] 策略
  • E [policy_effect] 效果
  • R [request_definition] 请求
  • M [matchers] 匹配

sub(subject)=请求实体 obj(object)=访问资源

act(action)=访问方法 (write,read) eft(effect)=策略结果

具体流程

  1. 系统设定策略 p, sub ,obj, act, (eft)
  2. 用户 在[request_definition]中 输入 sub , obj , act
  3. 在[matchers]中 将用户输入的和系统设定的策略相互匹配,匹配到了返回allow,否则deny,并把结果存入p.eft
  4. 在[policy_effect]中,如果匹配到,返回true,表示你获得权限,否则没有

实战

1
2
3
4
5
6
7
8
9
10
11
12
// 模型
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
  1. 示例
1
2
3
4
5
6
7
8
// 用户输入
alice, data1, read
// 系统设定策略(这个就是开发者可以修改)
p, alice, data1, read
p, bob, data2, write
// 对照发现第一条可以匹配得到
// 返回
true
  1. 示例
1
2
3
4
5
6
7
8
// 用户输入
alice, data1, read
// 系统设定策略(这个就是开发者可以修改)
p, alice, data1, read , deny
p, bob, data2, write
// 对照发现第一条可以匹配得到,但是匹配到的eft是deny
// 返回
false

同时,匹配规则是定死的,只有那么几个可以选

Policy Effect 含义
some(where (p.eft == allow)) 有一条匹配到就行
!some(where (p.eft == deny)) 只要存在一个策略的效果(eft)为拒绝(deny),那么访问就会被拒绝。
some(where (p.eft == allow)) && !some(where (p.eft == deny)) 要存在至少一个策略的效果为允许(allow),并且不存在任何一个策略的效果为拒绝(deny)
priority(p.eft) || deny 如果优先级存在(非零),或者出现了拒绝访问的情况
subjectPriority(p.eft) subjectPriority(p.eft)

总结

具体来说就是比较

用户输入数据系统设定策略比较

得到**比较结果,allow/deny

再用比较结果系统设定的比较结果相比较

返回true / deny 来判断是否有权限

单商户模型(进阶1)


在原来的模型上,引入角色(role)的概念,得到单商户模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

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

大多数地方都与上述的PERM元模型一致

[role_definition]
g = _, _

引入角色的概念,其实并不难理解,角色与用户是相等地位的,可以理解每个用户对应一个角色

g = _ ,_ 中 分别输入 g = 用户 ,角色 (具体设定是在策略中实现)

g(r.sub, p.sub) 代表了 Casbin 中的策略函数调用

说人话就是把用户和角色对应了起来

实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _ , _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
  1. 示例
1
2
3
4
5
6
7
8
9
10
11
// 用户输入           alice,想要访问data1,用于读的权限
alice, data1, read
// 系统策略
p, admin_alice, data1, read admin_alice 这个role角色读取data1的权限
p, alice, data1, read alice 本身用户拥有读取data1的权限

g, alice, admin_alice 将 alice用户 和 admin_alice 角色相绑定
// 匹配两者
allow
// 结果
true
  1. 对示例1稍微修改一下
1
2
3
4
5
6
7
8
9
10
11
// 用户输入           alice,想要访问data1,用于读的权限
alice, data1, read
// 系统策略
p, admin , data1, read admin 这个role角色读取data1的权限

g, alice, admin_alice 将 alice用户 和 admin_alice 角色相绑定
// 匹配两者
deny
// 结果
false
// alice获得的是admin_alice 的权限,而不是admin所以false
  1. 对示例1稍微修改一下啊
1
2
3
4
5
6
7
8
9
10
11
12
// 用户输入           alice,想要访问data1,用于读的权限
alice, data1, read
// 系统策略
p, admin, data1, read admin_alice 这个role角色读取data1的权限
p, alice, data1, read alice 本身用户拥有读取data1的权限

g, alice, admin_alice 将 alice用户 和 admin_alice 角色相绑定
// 匹配两者
allow
// 结果
true
// 虽然alice 没有获得admin的权限,但是他本身这个名字就有权限了,所以返回true

总结

角色用户 两者就是等价的,要用g(,)把两者绑定一下

然后就可以在策略中书写role的权限,可扩展性增加

多商户模型(进阶2)


在原来的模型上,引入 域(domain)的概念

可以把domain 理解为 某个角色/用户 在某个范围 可以做某些事情,但是在其他范围不能做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[request_definition]
r = sub, dom, obj, act

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

[role_definition]
g = _, _, _

[policy_effect]
e = some(where (p.eft == allow))

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

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

需要在 输入的时候 输入用户的domain

[role_definition]
g = _, _, _

这里有三个横线了,分别是 g = 用户,角色,域

用户和角色等价,两者在域之中

g(r.sub, p.sub, r.dom)

绑定一下关系 ,请求的实体和系统设定的实体需要在相同的domain中

实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[request_definition]
r = sub, dom, obj, act

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

[role_definition]
g = _, _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act
  1. 示例
1
2
3
4
5
6
7
8
9
10
11
// 用户输入
alice, domain1, data1, read 在domain1中的alice想要有data1的read权限

// 系统输入
p, alice, domain1,data1, read domain1的alice用户可以read来data1
p, admin, domain1,data1, read domain1的admin角色可以read来data1

g, alice, admin, domain1 alice用户--admin角色--属于domain1
// 比较 allow
// 返回
true
  1. 修改一下
1
2
3
4
5
6
7
8
9
10
11
12
// 用户输入
alice, domain1, data1, read 在domain1中的alice想要有data1的read权限

// 系统输入

p, admin, domain1,data1, read domain1的admin角色可以read来data1

g, alice, admin, domain2 alice用户--admin角色--属于domain2
// 比较 allow
// 返回
false
// 因为这里系统输入中是admin-domain2,所以与系统设定的策略admin-domain1不正确
  1. 再修改一下
1
2
3
4
5
6
7
8
9
10
11
12
// 用户输入
alice, domain1, data1, read 在domain1中的alice想要有data1的read权限

// 系统输入
p, alice, domain1,data1, read domain1的alice用户可以read来data1
p, admin, domain1,data1, read domain1的admin角色可以read来data1

g, alice, admin, domain2 alice用户--admin角色--属于domain1
// 比较 allow
// 返回
true
// 这里g, alice, admin, domain2虽然改成了domain2,但是这里是最纯粹的p, alice, domain1,data1, read 可以与输入的相互匹配

注意:

1
2
3
4
5
6
p, role , data, read
p, role , domain, data, read

// 这两个策略想要实现,必须要在策略中实现
g , 用户, _ , _
// 不然会输出false

总结


用户 可以理解为个人

角色 可以理解为某个职务

可以理解为某个部门

一般来说,都是某个某个职务在某个部门有哪些权限

如果要为某个人开个特定的权限,就可以直接写 p, alice , domain , data1, read 之类的