GO 权限治理之 Casbin

咱们来回顾一下上次分享的 GO中 gjson 库的利用和分享,它次要是提供了一种十分疾速简略的形式从json文档中获取相应值

  • 分享了 jsongjson别离代表什么
  • gjson 的简略应用
  • gjson 校验,获取值
  • gjsonjson 行
  • gjson的键门路匹配规定
  • gjson的修饰符和自定义修饰符

要是对 gjson还有点趣味的话,能够查看文章 GO中gjson的利用和分享

明天咱们来分享一下 GO外面的权限治理,Casbin

权限治理是什么?

个别指依据零碎设置的平安规定或者安全策略

用户能够拜访而且只能拜访本人被受权的资源,不多不少刚刚好

权限治理简直呈现在任何零碎外面

咱们可能会把 用户身份认证明码加密系统管理权限治理弄混同,那么他们具体的侧重点是什么呢?

  • 用户身份认证

不属于权限治理领域

用户身份认证指的是通过某种凭证来证实本人的身份,例如账号密码,指纹,人脸识别等等

  • 系统管理

是零碎中的一个模块,该模块个别还含有权限治理子模块 , 该模块相当于给权限治理模块提供了一些数据

  • 明码加密

也是不属于权限治理领域 , 他只是用户身份认证畛域的一个局部

Casbin 是个啥?

是 GO 我的项目的功能强大且高效的开源访问控制库,casbin反对罕用的多种访问控制模型,例如:

  • RBAC
  • ABAC
  • ACL

应用casbin来做权限治理有一个比拟好的中央是,casbin是反对多种语言的,就像protobuf一样也是反对多种语言

咱们来看看 Casbin 有啥个性

  • 施行策略是这样子的 {subject, object, action}

咱们也能够自定义,同时他反对容许受权和回绝受权

  • 他能够解决访问控制模型以及其存储对应的策略
  • RBAC中的角色层次结构 中,他能够治理角色用户映射和角色角色映射
  • 他反对内置的超级用户

rootadministrator

  • 反对多个内置运算符规定匹配

例如 hello/world ,就能够将其映射到 hello*模式

  • 不反对身份验证
  • 不反对治理用户或角色列表

咱们看一下 Casbin 的根本模型

Casbin 库中,他是基于PERM元模型将访问控制模型形象为CONF文件,有如下4个局部

  • 策略
  • 成果
  • 申请
  • 匹配器

一起来理解一个最简略的模型,ACLCONF模型

#申请定义[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模型的示例策略

p, xiaomt, data1, readp, xiaomt, data2, write

咱们来写一个DEMO

  • main.go 文件写gin 对应的接口以及 casbin 的应用
  • rbac_models.conf RBAC CONF文件

咱们写一个路由,外面增加一个拦截器,再写一个接口/api/v1/hello,应用GET办法验证成果

package mainimport (   "fmt"   "log"   "github.com/casbin/casbin"   xd "github.com/casbin/xorm-adapter"   "github.com/gin-gonic/gin"   _ "github.com/go-sql-driver/mysql")// myAuth 拦截器func myAuth(e *casbin.Enforcer) gin.HandlerFunc {   return func(c *gin.Context) {      obj := c.Request.URL.RequestURI()      // 获取办法      act := c.Request.Method      sub := "root"      // 判断策略是否曾经存在了      if ok := e.Enforce(sub, obj, act); ok {         log.Println("Check successfully")         c.Next()      } else {         log.Println("sorry , Check failed")         c.Abort()      }   }}func main() {   // 应用本人定义rbac_db   // 最初的一个参数咱们写true ,否则默认为false,应用缺省的数据库名casbin,不存在则创立   a := xd.NewAdapter("mysql", "root:123456@tcp(127.0.0.1:3306)/mycasbin?charset=utf8", true)   e := casbin.NewEnforcer("./rbac_models.conf", a)   //从DB中 load 策略   e.LoadPolicy()   //new 一个路由   r := gin.New()   r.POST("/api/v1/add", func(c *gin.Context) {      log.Println("add a policy")      if ok := e.AddPolicy("root", "/api/v1/hello", "GET"); !ok {         log.Println("The strategy already exists")      } else {         log.Println("add successfully ...")      }   })   //应用自定义拦截器中间件,每一个接口的拜访,都会通过这个拦截器   r.Use(myAuth(e))   //创立申请   r.GET("/api/v1/hello", func(c *gin.Context) {      fmt.Println("hello wolrd")   })   // 监听 127。0.0.1:8888   r.Run(":8888")}

对于上述 xd.NewAdapter 读取数据的操作,咱们能够看看具体实现

具体源码在 "github.com/casbin/xorm-adapter" 中的 adapter.go

// NewAdapter is the constructor for Adapter.// dbSpecified is an optional bool parameter. The default value is false.// It's up to whether you have specified an existing DB in dataSourceName.// If dbSpecified == true, you need to make sure the DB in dataSourceName exists.// If dbSpecified == false, the adapter will automatically create a DB named "casbin".func NewAdapter(driverName string, dataSourceName string, dbSpecified ...bool) *Adapter {   a := &Adapter{}   a.driverName = driverName   a.dataSourceName = dataSourceName   if len(dbSpecified) == 0 {      a.dbSpecified = false   } else if len(dbSpecified) == 1 {      a.dbSpecified = dbSpecified[0]   } else {      panic(errors.New("invalid parameter: dbSpecified"))   }   // Open the DB, create it if not existed.   a.open()   // Call the destructor when the object is released.   runtime.SetFinalizer(a, finalizer)   return a}

再来看看casbin.NewEnforcer

源码文件在 "github.com/casbin/casbin"enforcer.go

NewEnforcer 通过文件或 DB 创立一个 enforcer , 如下是官网的案例写法,留神如下案例

// e := casbin.NewEnforcer("path/to/basic_model.conf", "path/to/basic_policy.csv")// MySQL DB:// a := mysqladapter.NewDBAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/")// e := casbin.NewEnforcer("path/to/basic_model.conf", a)
func NewEnforcer(params ...interface{}) *Enforcer {   e := &Enforcer{}   parsedParamLen := 0   // 判断参数个数   if len(params) >= 1 {      enableLog, ok := params[len(params)-1].(bool)      if ok {         e.EnableLog(enableLog)         parsedParamLen++      }   }   // 省略 局部代码   return e}

上述代码,大家感兴趣的话,能够将代码贴到本人的环境中

应用相似postman工具来拜访接口,查看成果哦,须要配置好mysql数据库

对于上述的 gin拦截器 若感兴趣的话, 能够查看文章

  • 分享一波gin的路由算法
  • 瞧一瞧 gRPC的拦截器
  • Gin实战演练

总结

  • 分享了权限治理是什么
  • Casbin 是什么
  • Casbin 的个性
  • Casbin 的利用案例

欢送点赞,关注,珍藏

敌人们,你的反对和激励,是我保持分享,提高质量的能源

好了,本次就到这里,下一次 工作中后端是如何将API提供进来的?swaggo很不错

技术是凋谢的,咱们的心态,更应是凋谢的。拥抱变动,背阴而生,致力向前行。

我是小魔童哪吒,欢送点赞关注珍藏,下次见~