GO 权限管理之 Casbin

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: GO 权限管理之 Casbin

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, read
p, xiaomt, data2, write

咱们来写一个DEMO

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

咱们写一个路由,里面添加一个拦截器,再写一个接口/api/v1/hello,使用GET方法验证效果

package main
import (
   "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拦截器 若感兴趣的话, 可以查看文章

总结

  • 分享了权限管理是什么
  • Casbin 是什么
  • Casbin 的特性
  • Casbin 的应用案例

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

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

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

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

相关文章
|
2月前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
92 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
2月前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
47 7
|
2月前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
1天前
|
Go C语言
Go语言入门:分支结构
本文介绍了Go语言中的条件语句,包括`if...else`、`if...else if`和`switch`结构,并通过多个练习详细解释了它们的用法。`if...else`用于简单的条件判断;`if...else if`处理多条件分支;`switch`则适用于基于不同值的选择逻辑。特别地,文章还介绍了`fallthrough`关键字,用于优化重复代码。通过实例如判断年龄、奇偶数、公交乘车及成绩等级等,帮助读者更好地理解和应用这些结构。
27 14
|
2月前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
119 71
|
2月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
120 67
|
16天前
|
存储 监控 算法
内网监控系统之 Go 语言布隆过滤器算法深度剖析
在数字化时代,内网监控系统对企业和组织的信息安全至关重要。布隆过滤器(Bloom Filter)作为一种高效的数据结构,能够快速判断元素是否存在于集合中,适用于内网监控中的恶意IP和违规域名筛选。本文介绍其原理、优势及Go语言实现,提升系统性能与响应速度,保障信息安全。
25 5
|
25天前
|
算法 安全 Go
Go语言中的加密和解密是如何实现的?
Go语言通过标准库中的`crypto`包提供丰富的加密和解密功能,包括对称加密(如AES)、非对称加密(如RSA、ECDSA)及散列函数(如SHA256)。`encoding/base64`包则用于Base64编码与解码。开发者可根据需求选择合适的算法和密钥,使用这些包进行加密操作。示例代码展示了如何使用`crypto/aes`包实现对称加密。加密和解密操作涉及敏感数据处理,需格外注意安全性。
41 14
|
25天前
|
Go 数据库
Go语言中的包(package)是如何组织的?
在Go语言中,包是代码组织和管理的基本单元,用于集合相关函数、类型和变量,便于复用和维护。包通过目录结构、文件命名、初始化函数(`init`)及导出规则来管理命名空间和依赖关系。合理的包组织能提高代码的可读性、可维护性和可复用性,减少耦合度。例如,`stringutils`包提供字符串处理函数,主程序导入使用这些函数,使代码结构清晰易懂。
70 11
|
25天前
|
存储 安全 Go
Go语言中的map数据结构是如何实现的?
Go 语言中的 `map` 是基于哈希表实现的键值对数据结构,支持快速查找、插入和删除操作。其原理涉及哈希函数、桶(Bucket)、动态扩容和哈希冲突处理等关键机制,平均时间复杂度为 O(1)。为了确保线程安全,Go 提供了 `sync.Map` 类型,通过分段锁实现并发访问的安全性。示例代码展示了如何使用自定义结构体和切片模拟 `map` 功能,以及如何使用 `sync.Map` 进行线程安全的操作。