前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何把Casbin整合到Gin里面,让他支持RBAC鉴权?

如何把Casbin整合到Gin里面,让他支持RBAC鉴权?

作者头像
小锟哥哥
发布2022-05-10 08:53:56
1.2K0
发布2022-05-10 08:53:56
举报
文章被收录于专栏:GoLang全栈

我们之前基于本地配置文件写了一个最简单的入门 demo,这一篇我把他整合到 gin 里面。

配套Github代码

很开心的告诉大家,这个系列的文章我们会把代码开源到 Github 上,为大家学习的路上扫平一切障碍。

我们官方的 Github 代码阅读,地址如下:

代码语言:javascript
复制
https://github.com/GoLangStackDev/casbin-with-mysql-go.git

本文配套 tag 标记:整合到gin

编写基础的 gin 服务

看这个系列文章的同学应该都对 gin 有一定熟练度吧,如果你对 gin 并不熟悉,可以去我的另一个系列文章,否则后面的知识点你很可能看不懂。

这里直接上代码,在 main.go 文件里面写入这些内容:

代码语言:javascript
复制
r := gin.New()

r.GET("/posts", func(c *gin.Context) {

 c.JSON(http.StatusOK, gin.H{
  "msg": "所有文章",
 })
})
r.POST("/posts", func(c *gin.Context) {

 c.JSON(http.StatusOK, gin.H{
  "msg": "批量修改文章",
 })
})
if err:=r.Run(":8082");err!=nil {
 log.Panicln(err)
}

简单说下,我们基于 gin 创建了两个 API 分别对应上一篇文章 policy.csv 里面的这两个资源:

刚好 post 方法只有 admin 组的 super 用户才有权限。

编写中间件整合 casbin

现在我们基础的 API 有了,就需要做鉴权了,很明显我们不可能直接在每个API方法里面写鉴权代码。

我们需要编写一个中间件来进行鉴权处理。

我们在工程下面新建一个 package 名为 mid,当然名字你可以随便取名。

然后新建一个 mid.go 文件。

这里面我们需要编写 2 个中间件代码,分别是负责鉴权是否登录了,另一个负责 RBAC 鉴权,上代码:

代码语言:javascript
复制
// 校验是否登录
func CheekLogin() gin.HandlerFunc {
 return func(c *gin.Context) {

  if c.Request.Header.Get("token")=="" {
   c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
    "msg": "token required",
   })
  }else{
   c.Set("user_name", c.Request.Header.Get("token"))
   c.Next()
  }
 }
}

func RBAC() gin.HandlerFunc {
 e,_ := casbin.NewEnforcer("resources/model.conf","resources/policy.csv")

 return func(c *gin.Context) {
  user,_ := c.Get("user_name")
  if has,err:=e.Enforce(user,c.Request.RequestURI,c.Request.Method);err!=nil||!has {
   c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
    "msg": "forbidden",
   })
  }else{
   c.Next()
  }
 }
}

CheekLogin 方法

在 CheekLogin 方法里面我从请求头里面去取 token 字段,但是这个 token 并不是严格上的 token。

生产肯定是基于 JWT 的 token,然后解析出里面的 user_name。

我们这里为了方便演示,直接让传 user_name 当 token。

所以你就能看到在 else 里面,直接把 token 赋值给了 user_name。

RBAC 方法

上一篇文章我们定义了,一个请求要鉴权需要使用三个参数:sub,obj,act。

在 CheekLogin 中间件里面我们往 context 里面写入了 user_name 即 sub。

而剩下的 2 个参数,在 context 里面也能找到,分别是 c.Request.RequestURI 即 obj 和 c.Request.Method 即 act。

接下来就需要使用 casbin 去做权限校验了。

首先我们使用上一篇文章里面的 casbin.NewEnforcer 去创建一个 e 变量,随后和上一篇文章一样使用 Enforce 方法去校验。

得到的结果就是鉴权结果。

整合进 gin 里面

现在我们两个中间件都写好了,只需要整合到 gin 里面就大功告成了。

在 main 方法里面的加入以下代码即可:

代码语言:javascript
复制
r := gin.New()
r.Use(mid.CheekLogin(),mid.RBAC())

现在我们来测试下:

不传 token 会返回 400,现在我们随便传入一个 token 试试:

随便传的 token 会鉴权失败,返回403,现在传入配置里面的 lili 用户:

此时如果用 lili 用 POST 访问这个 API 呢?

会报 403 没权限,此时用 super 用户就能访问了:

我们的初步整合就完毕了!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GoLang全栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 配套Github代码
  • 编写基础的 gin 服务
  • 编写中间件整合 casbin
    • CheekLogin 方法
      • RBAC 方法
      • 整合进 gin 里面
      相关产品与服务
      消息队列 TDMQ
      消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档