Go 每日一库之 casbin

简介

权限管理在几乎每个系统中都是必备的模块。如果项目开发每次都要实现一次权限管理,无疑会浪费开发时间,增加开发成本。因此,casbin库出现了。casbin是一个强大、高效的访问控制库。支持常用的多种访问控制模型,如ACL/RBAC/ABAC等。可以实现灵活的访问权限控制。同时,casbin支持多种编程语言,Go/Java/Node/PHP/Python/.NET/Rust。我们只需要一次学习,多处运用

快速使用

我们依然使用 Go Module 编写代码,先初始化:

$ mkdir casbin && cd casbin
$ go mod init github.com/darjun/go-daily-lib/casbin

然后安装casbin,目前是v2版本:

$ go get github.com/casbin/casbin/v2

权限实际上就是控制能对什么资源进行什么操作。casbin将访问控制模型抽象到一个基于 PERM(Policy,Effect,Request,Matchers) 元模型的配置文件(模型文件)中。因此切换或更新授权机制只需要简单地修改配置文件。

policy是策略或者说是规则的定义。它定义了具体的规则。

request是对访问请求的抽象,它与e.Enforce()函数的参数是一一对应的

matcher匹配器会将请求与定义的每个policy一一匹配,生成多个匹配结果。

effect根据对请求运用匹配器得出的所有结果进行汇总,来决定该请求是允许还是拒绝

下面这张图很好地描绘了这个过程:

我们首先编写模型文件:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

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

上面模型文件规定了权限由sub,obj,act三要素组成,只有在策略列表中有和它完全相同的策略时,该请求才能通过。匹配器的结果可以通过p.eft获取,some(where (p.eft == allow))表示只要有一条策略允许即可。

然后我们策略文件(即谁能对什么资源进行什么操作):

p, dajun, data1, read
p, lizi, data2, write

上面policy.csv文件的两行内容表示dajun对数据data1read权限,lizi对数据data2write权限。

接下来就是使用的代码:

package main

import (
  "fmt"
  "log"

  "github.com/casbin/casbin/v2"
)

func check(e *casbin.Enforcer, sub, obj, act string) {
  ok, _ := e.Enforce(sub, obj, act)
  if ok {
    fmt.Printf("%s CAN %s %s\n", sub, act, obj)
  } else {
    fmt.Printf("%s CANNOT %s %s\n", sub, act, obj)
  }
}

func main() {
  e, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
  if err != nil {
    log.Fatalf("NewEnforecer failed:%v\n", err)
  }

  check(e, "dajun", "data1", "read")
  check(e, "lizi", "data2", "write")
  check(e, "dajun", "data1", "write")
  check(e, "dajun", "data2", "read")
}

代码其实不复杂。首先创建一个casbin.Enforcer对象,加载模型文件model.conf和策略文件policy.csv,调用其Enforce方法来检查权限。运行程序:

$ go run main.go
dajun CAN read data1
lizi CAN write data2
dajun CANNOT write data1
dajun CANNOT read data2

请求必须完全匹配某条策略才能通过。("dajun", "data1", "read")匹配p, dajun, data1, read("lizi", "data2", "write")匹配p, lizi, data2, write,所以前两个检查通过。第 3 个因为"dajun"没有对data1write权限,第 4 个因为dajundata2没有read权限,所以检查都不能通过。输出结果符合预期。

sub/obj/act依次对应传给Enforce方法的三个参数。实际上这里的sub/obj/actread/write/data1/data2是我自己随便取的,你完全可以使用其它的名字,只要能前后一致即可。

上面例子中实现的就是ACL(access-control-list,访问控制列表)。ACL显示定义了每个主体对每个资源的权限情况,未定义的就没有权限。我们还可以加上超级管理员,超级管理员可以进行任何操作。假设超级管理员为root,我们只需要修改匹配器:

[matchers]
e = r.sub == p.sub && r.obj == p.obj && r.act == p.act || r.sub == "root"

只要访问主体是root

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值