关于Casbin
Casbin是用于Golang项目的功能强大且高效的开源访问控制库。
casbin中文官方文档
Casbin的作用
- 以经典{subject, object, action}形式或您定义的自定义形式实施策略,同时支持允许和拒绝授权。
- 处理访问控制模型及其策略的存储。
- 管理角色用户映射和角色角色映射(RBAC中的角色层次结构)。
- 支持内置的超级用户,例如root或administrator。超级用户可以在没有显式权限的情况下执行任何操作。
- 多个内置运算符支持规则匹配。例如,keyMatch可以将资源键映射/foo/bar到模式/foo*。
Casbin不执行的操作
- 身份验证(又名验证username以及password用户登录时)
- 管理用户或角色列表。我相信项目本身管理这些实体会更方便。用户通常具有其密码,而Casbin并非设计为密码容器。但是,Casbin存储RBAC方案的用户角色映射。
它是怎么运行的
在Casbin中,基于PERM元模型(策略,效果,请求,匹配器)将访问控制模型抽象为CONF文件。因此,切换或升级项目的授权机制就像修改配置一样简单。您可以通过组合可用的模型来定制自己的访问控制模型。例如,您可以在一个模型中同时获得RBAC角色和ABAC属性,并共享一组策略规则。
Casbin中最基本,最简单的模型是ACL。ACL的CONF模型为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #请求定义 [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
|
ACL模型的示例策略如下:
1 2
| p, alice, data1, read p, bob, data2, write
|
安装
1
| go get github.com/casbin/casbin
|
装完后go mod init和go mod tidy后,本机安装的默认版本是:
1 2
| github.com/casbin/casbin v1.9.1 github.com/casbin/xorm-adapter v1.0.0
|
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| package main
import ( "fmt"
"github.com/casbin/casbin" xormadapter "github.com/casbin/xorm-adapter" "github.com/gin-gonic/gin" _ "github.com/go-sql-driver/mysql" )
func main() { a := xormadapter.NewAdapter("mysql", "root:mysql123@tcp(127.0.0.1:3306)/goblog?charset=utf8", true) e := casbin.NewEnforcer("./rbac_models.conf", a) e.LoadPolicy()
r := gin.New()
r.POST("/api/v1/add", func(c *gin.Context) { fmt.Println("增加Policy") if ok := e.AddPolicy("admin", "/api/v1/hello", "GET"); !ok { fmt.Println("Policy已经存在") } else { fmt.Println("增加成功") } }) r.DELETE("/api/v1/delete", func(c *gin.Context) { fmt.Println("删除Policy") if ok := e.RemovePolicy("admin", "/api/v1/hello", "GET"); !ok { fmt.Println("Policy不存在") } else { fmt.Println("删除成功") } }) r.GET("/api/v1/get", func(c *gin.Context) { fmt.Println("查看policy") list := e.GetPolicy() for _, vlist := range list { for _, v := range vlist { fmt.Printf("value: %s, ", v) } } }) r.Use(Authorize(e)) r.GET("/api/v1/hello", func(c *gin.Context) { fmt.Println("Hello 接收到GET请求..") }) r.POST("/api/v1/hello", func(c *gin.Context) { fmt.Println("Hello 接收到POST请求..") })
r.Run(":9000") }
func Authorize(e *casbin.Enforcer) gin.HandlerFunc {
return func(c *gin.Context) {
obj := c.Request.URL.RequestURI() act := c.Request.Method sub := "admin"
if ok := e.Enforce(sub, obj, act); ok { fmt.Println("恭喜您,权限验证通过") c.Next() } else { fmt.Println("很遗憾,权限验证没有通过") c.Abort() } } }
|
rbac_models.conf里面的内容如下:
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
|
运行
命令行输入go run main.go
后,会自动在本地数据库goblog
下创建一个名为casbin_rule
的表
使用postman发送Get请求到http://localhost:9000/api/v1/hello
输出为:很遗憾,权限验证没有通过
接着我们往casbin_rule
表里添加以下内容:
再次使用postman发送Get请求到http://localhost:9000/api/v1/hello
输出为:
1 2
| 恭喜您,权限验证通过 Hello 接收到GET请求..
|
按照数据表里的逻辑,我们再试试用postman发送POST请求到http://localhost:9000/api/v1/hello
输出为:
1 2
| 恭喜您,权限验证通过 Hello 接收到POST请求..
|
如果我们再试一下用postman发送DELETE请求到http://localhost:9000/api/v1/hello
输出为:很遗憾,权限验证没有通过
小结
通过以上个人实验,我觉得使用Casbin的作用就是把用户对应请求接口的权限放在MySQL数据库中去记录,因此权限验证这个模块可以完全独立出来,使得给某用户添加某接口的某种(常用POST、GET、DELETE、GET)请求的权限都会一目了然。
以上代码github地址