文章目录
- 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
为例
#mermaid-svg-rVLJdcTlkoc0A3kM {font-family:”trebuchet ms”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rVLJdcTlkoc0A3kM .error-icon{fill:#552222;}#mermaid-svg-rVLJdcTlkoc0A3kM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rVLJdcTlkoc0A3kM .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-rVLJdcTlkoc0A3kM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rVLJdcTlkoc0A3kM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rVLJdcTlkoc0A3kM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rVLJdcTlkoc0A3kM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rVLJdcTlkoc0A3kM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rVLJdcTlkoc0A3kM .marker.cross{stroke:#333333;}#mermaid-svg-rVLJdcTlkoc0A3kM svg{font-family:”trebuchet ms”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rVLJdcTlkoc0A3kM .label{font-family:”trebuchet ms”,服务器托管网verdana,arial,sans-serif;color:#333;}#mermaid-svg-rVLJdcTlkoc0A3kM .cluster-label text{fill:#333;}#mermaid-svg-rVLJd服务器托管网cTlkoc0A3kM .cluster-label span{color:#333;}#mermaid-svg-rVLJdcTlkoc0A3kM .label text,#mermaid-svg-rVLJdcTlkoc0A3kM span{fill:#333;color:#333;}#mermaid-svg-rVLJdcTlkoc0A3kM .node rect,#mermaid-svg-rVLJdcTlkoc0A3kM .node circle,#mermaid-svg-rVLJdcTlkoc0A3kM .node ellipse,#mermaid-svg-rVLJdcTlkoc0A3kM .node polygon,#mermaid-svg-rVLJdcTlkoc0A3kM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rVLJdcTlkoc0A3kM .node .label{text-align:center;}#mermaid-svg-rVLJdcTlkoc0A3kM .node.clickable{cursor:pointer;}#mermaid-svg-rVLJdcTlkoc0A3kM .arrowheadPath{fill:#333333;}#mermaid-svg-rVLJdcTlkoc0A3kM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rVLJdcTlkoc0A3kM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rVLJdcTlkoc0A3kM .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-rVLJdcTlkoc0A3kM .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-rVLJdcTlkoc0A3kM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rVLJdcTlkoc0A3kM .cluster text{fill:#333;}#mermaid-svg-rVLJdcTlkoc0A3kM .cluster span{color:#333;}#mermaid-svg-rVLJdcTlkoc0A3kM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:”trebuchet ms”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rVLJdcTlkoc0A3kM :root{–mermaid-font-family:”trebuchet ms”,verdana,arial,sans-serif;}
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,POST
g,leo,admin
2. 库使用
2.1 Enforcer 执行器概念
Casbin 库中核心概念为
执行器Enforcer
使用casbin.NewEnforcer("./model.conf", "./policy.csv")
加载模型
和策略
调用Enforcer的Enforce(r.sub, r.obj, r.act)
方法检查鉴权结果
package main
import (
"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 main
import (
"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
结合起来,并实现增删改查
功能
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net