文章目录
- 0. 背景
- 1. 核心概念
- 1.1 Model
- 1.2 Policy
- 1.3 实例分析
- 1.3 ACL模型和RBAC模型
- 1.3.1 ACL模型
- 1.3.2 RBAC模型
- 2. 库使用
- 2.1 Enforcer 执行器概念
- 2.2 adapter 适配器概念
- 2.3 Functions(Matchers中的函数)
- 3. 结语
0. 背景
Casbin是用于Golang项目的功能强大且高效的开源访问控制库。
强大通用也意味着概念和配置较多,具体到实际应用(以Gin Web框架开发)需要解决以下问题:
- 权限配置的存储,以及
增删改查
- Gin框架的中间件如何实现
经过一番摸索实践出经验,计划分为三个章节,循序渐进的介绍使用方法
1. Casbin概念介绍以及库使用
2. 使用Gorm存储Casbin权限配置以及增删改查
3.实现Gin鉴权中间件
代码地址 https://gitee.com/leobest2/gin-casbin-example
1. 核心概念
核心配置中含两部分
模型配置
以及策略配置
,给出两个示范配置,在此基础上对实际请求进行分析。
1.1 Model
模型文件,存储了请求定义(request_definition),策略定义(policy_definition),匹配规则(matchers),以及匹配的综合结果(policy_effect)
[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.2 Policy
以下为示策略文件
policy.csv
含有两条策略,策略除了存储在文件中,还可以保存到数据库,后续中我们用到GORM Adapter
,保存到数据库中
p,leo,/api/user,GET
p,leo,/api/user,POST
1.3 实例分析
以用户
leo
通过GET
方法访问后台API:/api/user
为例
1.3 ACL模型和RBAC模型
Casbin模型比较多,只需理解以下两种模型,基本能满足绝大部分业务需求
1.3.1 ACL模型
简单理解,如上面
model.conf
中不包含用户角色组,策略中都是针对单个用户,用户的请求和动作直接匹配策略,并计算结果
1.3.2 RBAC模型
简单理解,用户关联到角色组,策略定义中针对组做策略
后续gin casbin鉴权中选用该模型
后续示例中model.conf
[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
后续示例中policy.csv
定义了两条策略,
admin
组能访问的资源以及操作,以及用户leo
属于admin
组
p,admin,/api/user,GET
p,admin,/api/user,POSTg,leo,admin
2. 库使用
2.1 Enforcer 执行器概念
Casbin 库中核心概念为
执行器Enforcer
使用casbin.NewEnforcer("./model.conf", "./policy.csv")
加载模型
和策略
调用Enforcer的Enforce(r.sub, r.obj, r.act)
方法检查鉴权结果
package mainimport ("fmt""github.com/casbin/casbin/v2"
)func CheckPermission(e *casbin.Enforcer, sub, obj, act string) {ok, err := e.Enforce(sub, obj, act)if err != nil {panic("check enforce error: " + err.Error())}if ok {fmt.Printf("用户: %s 访问资源: %s 使用方法: %s 检查通过\n", sub, obj, act)} else {fmt.Printf("用户: %s 访问资源: %s 使用方法: %s 检查拒绝\n", sub, obj, act)}
}func main() {enforcer, err := casbin.NewEnforcer("./model.conf", "./policy.csv")if err != nil {panic("new enforcer error: " + err.Error())}// 预期输出:// 用户: leo 访问资源: /api/user 使用方法: GET 检查通过CheckPermission(enforcer, "leo", "/api/user", "GET")// 预期输出:// 用户: leo 访问资源: /api/user 使用方法: DELETE 检查拒绝CheckPermission(enforcer, "leo", "/api/user", "DELETE")
}
2.2 adapter 适配器概念
casbin.NewEnforcer(“./model.conf”, “./policy.csv”)中默认从文件加载,是内置的名为
File Adapter (内置)
实现的
后续中,我们需将权限存储到DB中,使用的适配器为GORM Adapter
,使用如下:
package mainimport ("log""github.com/casbin/casbin/v2"gormadapter "github.com/casbin/gorm-adapter/v3""github.com/glebarez/sqlite""gorm.io/gorm"
)func main() {db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})if err != nil {panic("failed to connect database")}a, err := gormadapter.NewAdapterByDB(db)if err != nil {panic("new gorm adapter error: " + err.Error())}e, err := casbin.NewEnforcer("./model.conf", a)if err != nil {panic("new casbin enforcer error: " + err.Error())}e.LoadPolicy()// 添加策略ok, err := e.AddPolicy("admin", "/api/user", "GET")log.Println("add admin /api/user GET: ", ok, err)ok, err = e.AddGroupingPolicy("leo", "admin")log.Println("add leo to admin group: ", ok, err)e.SavePolicy()ok, err = e.Enforce("leo", "/api/user", "GET")log.Println("leo GET /api/user :", ok, err)ok, err = e.Enforce("leo", "/api/user", "DELETE")log.Println("leo DELETE /api/user :", ok, err)
}
测试结果
2.3 Functions(Matchers中的函数)
上述
model.conf
中有一个问题,访问的url是/api/user/123
形式,r.obj
与p.obj
不匹配,这时候我们要用到Matchers中的函数,一般选择keyMatch2
即可能针对url,能满足日常需求
修改后的model.conf
[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) && keyMatch2(r.obj,p.obj) && r.act == p.act
更多函数参考,https://casbin.org/zh/docs/function
函数 | url | 模式 |
---|---|---|
keyMatch | 一个URL 路径,例如/alice_data/resource1 | 一个URL 路径或* 模式下,例如/alice_data/* |
keyMatch2 | 一个URL 路径,例如/alice_data/resource1 | 一个URL 路径或: 模式下,例如/alice_data/:resource |
keyMatch3 | 一个URL 路径,例如/alice_data/resource1 | 一个URL 路径或{} 模式下,例如/alice_data/{resource} |
keyMatch4 | 一个URL 路径,例如/alice_data/resource1 | 一个URL 路径或{} 模式下,例如/alice_data//{id}/book/{id} |
keyMatch5 | a URL path like/alice_data/123/?status=1 | a URL path, a{} or* pattern like/alice_data/{id}/* |
regexMatch | 任意字符串 | 正则表达式模式 |
3. 结语
至此,已了解的概念已能满足业务需求,下一章将
Casbin
与Gorm
结合起来,并实现增删改查
功能