之前的两篇文章,我们做demo的时候,把所有的代码都写在main.go里.在进一步深入学习casbin之前,把代码做一次重构.重构完成后,目录结构是这样的:
首先,把配置文件rbac_models.conf移到conf目录下.
其次,把main.go初始化casbin的代码,放到service/casbin.go里,代码如下:
package service
import (
"log"
"github.com/casbin/casbin/v2"
xormadapter "github.com/casbin/xorm-adapter/v2"
_ "github.com/go-sql-driver/mysql"
)
var Enforcer *casbin.Enforcer
// 初始化casbin
func CasbinSetup() {
a, err := xormadapter.NewAdapter("mysql", "rbac:123456@tcp(127.0.0.1:3306)/rbac_db?charset=utf8", true)
if err != nil {
log.Printf("连接数据库错误: %v", err)
return
}
e, err := casbin.NewEnforcer("conf/rbac_models.conf", a)
if err != nil {
log.Printf("初始化casbin错误: %v", err)
return
}
Enforcer = e
}
第三步,把main.go里关于拦截器的部分,放到middleware/middleware.go里,代码如下:
package middleware
import (
"demo/service"
"fmt"
"github.com/gin-gonic/gin"
)
//拦截器
func Authorize() gin.HandlerFunc {
return func(c *gin.Context) {
// var e *casbin.Enforcer
e := service.Enforcer
//从DB加载策略
e.LoadPolicy()
//获取请求的URI
obj := c.Request.URL.RequestURI()
//获取请求方法
act := c.Request.Method
//获取用户的角色
sub := "admin"
//判断策略中是否存在
if ok, _ := e.Enforce(sub, obj, act); ok {
fmt.Println("恭喜您,权限验证通过")
c.Next()
} else {
fmt.Println("很遗憾,权限验证没有通过")
c.Abort()
}
}
}
第四步,把main.go里的
r.GET("/api/v1/hello", func(c *gin.Context) {
fmt.Println("Hello 接收到GET请求..")
})
这部分代码,放到controller/hello.go里,代码如下:
package controller
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func Hello(c *gin.Context) {
fmt.Println("Hello 接收到GET请求..")
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": "Success",
"data": "Hello 接收到GET请求..",
})
}
第五步,把main.go里路由部分的代码,放到routers/router.go里,代码如下:
package routers
import (
"demo/controller"
"demo/middleware"
"github.com/gin-gonic/gin"
)
func InitRouter() *gin.Engine {
//获取router路由对象
r := gin.New()
//使用自定义拦截器中间件
r.Use(middleware.Authorize())
//创建请求
r.GET("/api/v1/hello", controller.Hello)
return r
}
经过这样改造后,main.go里的内容就少多了:
package main
import (
"demo/routers"
"demo/service"
)
func init() {
service.CasbinSetup()
}
func main() {
r := routers.InitRouter()
r.Run(":9000") //参数为空 默认监听8080端口
}
最后使用postman模拟访问,输出如下: