casbin访问控制库详解

casbin是一个强大、高效的访问控制库。支持常用的多种访问控制模型,如ACL/RBAC/ABAC等。可以实现灵活的访问权限控制。同时,casbin支持多种编程语言,Go/Java/Node/PHP/Python/.NET/Rust。本文以Go作为示例进行描述。

一、例子1

先来看第一个例子,在这个例子中,我们控制用户名为“admin”的用户对web路径“/user/*”,有“get”的访问权限,用户“user”对web路径“/goods/list”有“post”访问权限,用户“root”对一切都有访问权限。

1. 引入库

require github.com/casbin/casbin v1.9.1

2. 访问控制模型(abac_model.conf)

[request_definition]
r = user, path, method

[policy_definition]
p = user, path, method

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

[matchers]
m = r.user == p.user && keyMatch(r.path , p.path) && r.method == p.method || r.user == "root"

3. 访问策略(abac_policy.csv)

p, admin, /user/*, get
p, user, /goods/list, post

4. 程序

package main

import (
	"github.com/casbin/casbin"
	"log"
)

func main() {

	e:= casbin.NewEnforcer("./abac_model.conf","./abac_policy.csv")

	enforce := e.Enforce("a", "/user/list", "get")
	log.Printf("\"a\", \"/user/list\", \"get\"->%v\n",enforce)
	enforce = e.Enforce("a", "/user/add", "get")
	log.Printf("\"a\", \"/user/add\", \"get\"->%v\n",enforce)

	enforce = e.Enforce("admin", "/user/add", "get")
	log.Printf("\"admin\", \"/user/add\", \"get\"->%v\n",enforce)
	enforce = e.Enforce("admin", "/user/add", "get")
	log.Printf("\"admin\", \"/user/add\", \"get\"->%v\n",enforce)
	enforce = e.Enforce("admin", "/user/list", "get")
	log.Printf("\"admin\", \"/user/list\", \"get\"->%v\n",enforce)
	enforce = e.Enforce("admin", "/user/add", "post")
	log.Printf("\"admin\", \"/user/add\", \"post\"->%v\n",enforce)
	enforce = e.Enforce("admin", "/goods/list", "post")
	log.Printf("\"admin\", \"/goods/list\", \"post\"->%v\n",enforce)

	enforce = e.Enforce("user", "/user/add", "get")
	log.Printf("\"user\", \"/user/add\", \"get\"->%v\n",enforce)
	enforce = e.Enforce("user", "goods/list", "get")
	log.Printf("\"user\", \"goods/list\", \"get\"->%v\n",enforce)
	enforce = e.Enforce("user", "/goods/list", "post")
	log.Printf("\"user\", \"/goods/list\", \"post\"->%v\n",enforce)

	enforce = e.Enforce("root", "/user/add", "get")
	log.Printf("\"root\", \"/user/add\", \"get\"->%v\n",enforce)
	enforce = e.Enforce("root", "goods/list", "get")
	log.Printf("\"root\", \"goods/list\", \"get\"->%v\n",enforce)
	enforce = e.Enforce("root", "/goods/list", "post")
	log.Printf("\"root\", \"/goods/list\", \"post\"->%v\n",enforce)
	enforce = e.Enforce("root", "/aa/add", "post")
	log.Printf("\"root\", \"/aa/add\", \"post\"->%v\n",enforce)

}

5. 结果

2021/05/30 17:42:09 "a", "/user/list", "get"->false
2021/05/30 17:42:09 "a", "/user/add", "get"->false
2021/05/30 17:42:09 "admin", "/user/add", "get"->true
2021/05/30 17:42:09 "admin", "/user/add", "get"->true
2021/05/30 17:42:09 "admin", "/user/list", "get"->true
2021/05/30 17:42:09 "admin", "/user/add", "post"->false
2021/05/30 17:42:09 "admin", "/goods/list", "post"->false
2021/05/30 17:42:09 "user", "/user/add", "get"->false
2021/05/30 17:42:09 "user", "goods/list", "get"->false
2021/05/30 17:42:09 "user", "/goods/list", "post"->true
2021/05/30 17:42:09 "root", "/user/add", "get"->true
2021/05/30 17:42:09 "root", "goods/list", "get"->true
2021/05/30 17:42:09 "root", "/goods/list", "post"->true
2021/05/30 17:42:09 "root", "/aa/add", "post"->true

6. 说明

其实casbin的使用非常简单

第一步,初始化一个Enforcer:
e:= casbin.NewEnforcer("./abac_model.conf","./abac_policy.csv")
第二步,对输入参数进行验证,例如:
enforce := e.Enforce(“a”, “/user/list”, “get”)

通过观察输出结果,我们可以看到,我们实现了我们要达到的访问控制效果。那么整个过程是怎么实现的呢,下面我们来详细说明下。

二、访问控制模型

首先我们来看访问控制模型(abac_model.conf),在这个文件中,我们定义了访问控制的规则:

1.请求定义

在模型中, [request_definition]后面一行就是请求定义,它定义了我们的输入参数,也就是方法e.Enforce(“a”, “/user/list”, “get”),各个参数的意义,比如在上面的例子中,第一个参数是用户名,第二个参数是web访问路径,第三个参数是访问方法。需要注意的是,在进行验证的时候,传入参数一定要和模型中定义的一致。

2.策略定义

策略定义是以 [policy_definition]开始的,其后面的内容就是策略定义。这里定义了每条策略各个子项的含义。在上面的例子中,它定义了一条策略中,第一项是用户名,第二项是web访问路径,第三项是访问方法。在后面制定策略的时候就按照这个定义来做,比如上面的例子了,可以看到策略文件中,p后面分别是用户名,web访问路径,访问方法。

3. 策略效果

策略效果以[policy_effect]开始,是用来说明,各个匹配结果怎样对最终结果产生影响,比如上面例子中的策略效果:e = some(where (p.eft == allow)),它表示只要有一条策略记录和请求参数匹配了,那么最终结果就是allow。

4. 匹配器

匹配器以[matchers]开始,它说明了,输入参数和策略记录怎样进行匹配,比如上面的例子中(m = r.user == p.user && keyMatch(r.path , p.path) && r.method == p.method || r.user == “root”),它的意思是,输入参数的用户名和策略记录中的用户名要相当,并且输入参数和策略记录中的web访问路径要匹配,并且输入参数和策略记录中的方法字段要相当,同时满足这3个条件则输入参数和策略记录是匹配的,结果是allow的;或者符号“||”,说明前面3个条件没有同时满足,但是输入请求用户名是root,那么输入请求就是和策略记录匹配的,结果是allow的。特别说明一下,匹配器里面可以使用函数,比如上面例子中的keyMatch,也可以自定义函数,细节可以参考官方文档,这里不详述。

三、策略记录

策略记录是记录了,访问策略的记录,它可以用文件进行保存,也可以保存到数据,通过不同adapter的来实现。细节请参考官方文档关于adapter的叙述。

四、例子2

通过例子1的分析,我们可以发现,casbin的规则定义是比较灵活的,要验证什么内容,怎样验证,我们都可以自定义的。我们再来看一个例子,我们现在有一个功能只能ip地址为192.168开头的用户才能访问。

1. 访问控制模型(abac_model.conf)

[request_definition]
r = act, ip

[policy_definition]
p = act, ip

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

[matchers]
m = r.act == p.act&& keyMatch(r.ip, p.ip)

3. 访问策略(abac_policy.csv)

p, admin, 192.168*

4. 程序

package main

import (
	"github.com/casbin/casbin"
	"log"
)

func main() {
	e:= casbin.NewEnforcer("./abac_model.conf","./abac_policy.csv")

	enforce := e.Enforce("admin", "192.168.0.11")
	log.Printf("\"admin\", \"192.168.0.11\"->%v\n",enforce)
	enforce = e.Enforce("admin", "192.167.0.11")
	log.Printf("\"admin\", \"192.167.0.11\"->%v\n",enforce)
	enforce = e.Enforce("manage", "192.168.0.11")
	log.Printf("\"manage\", \"192.168.0.11\"->%v\n",enforce)
}

5. 结果

2021/05/30 20:30:23 "admin", "192.168.0.11"->true
2021/05/30 20:30:23 "admin", "192.167.0.11"->false
2021/05/30 20:30:23 "manage", "192.168.0.11"->false

可以看到,只有第一个请求是allow的,第二个是因为ip地址不匹配,第三个是功能不匹配。

五、分组

在权限控制里面,我们常常有这样的需求,那就是我们希望我们可以定义一些角色,给这些角色赋予某些权限,然后给用户指定某些角色,从而使用户具有角色所拥有的所有权限。要达到这个效果,在casbin里面要怎么去做呢?还是来看看下面的例子吧。

1. 访问控制模型(rbac_model.conf)

[request_definition]
r = user, path, method

[policy_definition]
p = role, path, method

[role_definition]
g = _, _

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

[matchers]
m = g(r.user, p.role) && keyMatch(r.path , p.path) && r.method == p.method

2. 访问策略(rbac_policy.csv)

p, manager, /user/*, get
p, seller, /goods/list, post

g, admin, manager
g, admin, seller
g, user1, seller

3.结果

admin,/user/list,get   -->true
admin,/goods/list,post   -->true
user1,/user/list,get   -->false
user1,/goods/list,post   -->true

4.说明

通过上面的例子,我们可以看到,我们在控制模型中加上[role_definition],在匹配器中加上g(r.user, p.role)就能达到我们引入角色的目的。其实,g(r.user, p.role)的作用就是从请求参数中拿出user参数,从策略记录中拿出role字段,然后和分组记录(访问策略文件中g开头的记录)进行匹配,如果匹配到了g(r.user, p.role)的结果就是true。

六、后记

由于本人也是刚接触casbin,有什么阐述得不对的,欢迎留言指正。另外,casbin的官网地址如下:casbin官网;官网提供的编辑器,可以用来验证策略记录是否正确:https://casbin.org/en/editor/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值