我们之前基于本地配置文件写了一个最简单的入门 demo,这一篇我把他整合到 gin 里面。
很开心的告诉大家,这个系列的文章我们会把代码开源到 Github 上,为大家学习的路上扫平一切障碍。
我们官方的 Github 代码阅读,地址如下:
https://github.com/GoLangStackDev/casbin-with-mysql-go.git
本文配套 tag 标记:整合到gin
看这个系列文章的同学应该都对 gin 有一定熟练度吧,如果你对 gin 并不熟悉,可以去我的另一个系列文章,否则后面的知识点你很可能看不懂。
这里直接上代码,在 main.go 文件里面写入这些内容:
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 用户才有权限。
现在我们基础的 API 有了,就需要做鉴权了,很明显我们不可能直接在每个API方法里面写鉴权代码。
我们需要编写一个中间件来进行鉴权处理。
我们在工程下面新建一个 package 名为 mid,当然名字你可以随便取名。
然后新建一个 mid.go 文件。
这里面我们需要编写 2 个中间件代码,分别是负责鉴权是否登录了,另一个负责 RBAC 鉴权,上代码:
// 校验是否登录
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 方法里面我从请求头里面去取 token 字段,但是这个 token 并不是严格上的 token。
生产肯定是基于 JWT 的 token,然后解析出里面的 user_name。
我们这里为了方便演示,直接让传 user_name 当 token。
所以你就能看到在 else 里面,直接把 token 赋值给了 user_name。
上一篇文章我们定义了,一个请求要鉴权需要使用三个参数:sub,obj,act。
在 CheekLogin 中间件里面我们往 context 里面写入了 user_name 即 sub。
而剩下的 2 个参数,在 context 里面也能找到,分别是 c.Request.RequestURI 即 obj 和 c.Request.Method 即 act。
接下来就需要使用 casbin 去做权限校验了。
首先我们使用上一篇文章里面的 casbin.NewEnforcer 去创建一个 e 变量,随后和上一篇文章一样使用 Enforce 方法去校验。
得到的结果就是鉴权结果。
现在我们两个中间件都写好了,只需要整合到 gin 里面就大功告成了。
在 main 方法里面的加入以下代码即可:
r := gin.New()
r.Use(mid.CheekLogin(),mid.RBAC())
现在我们来测试下:
不传 token 会返回 400,现在我们随便传入一个 token 试试:
随便传的 token 会鉴权失败,返回403,现在传入配置里面的 lili 用户:
此时如果用 lili 用 POST 访问这个 API 呢?
会报 403 没权限,此时用 super 用户就能访问了:
我们的初步整合就完毕了!