项目地址:

https://casbin.org/zh/docs/overview

示例代码:

  1. 基于文件:

    1. model.conf

      [request_definition]
      r = sub, obj, act
      
      [policy_definition]
      p = sub, obj, act
      
      [role_definition]
      g = _, _
      
      [policy_effect]
      e = some(where (p.eft == allow))
      
      [matchers]
      # root 是超级用户
      m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act || r.sub == "root"
    2. policy.csv

      p, admin, /test, POST
      p, admin, /test, DELETE
      p, a, /test, PUT
      g, a, admin
    3. main.go

       package main
      
       import (
           "fmt"
           "github.com/casbin/casbin/v2"
           "github.com/gin-gonic/gin"
           "net/http"
       )
      
       var (
           e   *casbin.Enforcer
           err error
       )
      
       func init() {
           e, err = casbin.NewEnforcer("model.conf", "policy.csv")
           if err != nil {
               panic(err)
           }
       }
      
       func checkPermission(ctx *gin.Context) {
           sub := ctx.GetHeader("user")
           obj := ctx.Request.URL.Path
           act := ctx.Request.Method
           ok, err := e.Enforce(sub, obj, act)
           if err != nil {
               ctx.String(http.StatusInternalServerError, "内部服务器错误")
               ctx.Abort()
           }
           if !ok {
               ctx.String(http.StatusOK, "权限验证不通过")
               ctx.Abort()
           }
           fmt.Println("权限验证通过")
           ctx.Next()
       }
      
       func main() {
           r := gin.Default()
           r.Use(checkPermission)
           // 新增策略
           r.PUT("/policy", func(ctx *gin.Context) {
               sub := ctx.Query("user")
               obj := ctx.Query("path")
               act := ctx.Query("method")
               role := ctx.Query("group")
               if ok, err := e.AddPolicy(sub, obj, act); !ok || err != nil {
                   ctx.String(http.StatusOK, "新增策略失败")
                   return
               }
               if role != "" {
                   if ok, err := e.AddRoleForUser(sub, role); !ok || err != nil {
                       ctx.String(http.StatusOK, "新增策略分组失败")
                       return
                   }
               }
               // 写入策略(保存到文件/数据库)
               e.SavePolicy()
               ctx.String(http.StatusOK, "新增策略成功")
               return
           })
           // 删除策略
           r.DELETE("/policy", func(ctx *gin.Context) {
               sub := ctx.Query("user")
               obj := ctx.Query("path")
               act := ctx.Query("method")
               role := ctx.Query("group")
               if ok, err := e.RemovePolicy(sub, obj, act); !ok || err != nil {
                   ctx.String(http.StatusOK, "删除策略失败")
                   return
               }
               if role != "" {
                   if ok, err := e.DeleteRoleForUser(sub, role); !ok || err != nil {
                       ctx.String(http.StatusOK, "删除策略分组失败")
                       return
                   }
               }
               // 写入策略(保存到文件/数据库)
               e.SavePolicy()
               ctx.String(http.StatusOK, "删除策略成功")
               return
           })
           // 策略列表
           r.GET("/policy", func(ctx *gin.Context) {
               list := e.GetPolicy()
               ctx.JSON(http.StatusOK, list)
               return
           })
           // 删除用户(同时删除【策略】和【分组】)
           r.DELETE("/user", func(ctx *gin.Context) {
               sub := ctx.Query("user")
               // 删除指定用户
               if ok, err := e.DeleteUser(sub); !ok || err != nil {
                   ctx.String(http.StatusOK, "删除用户失败")
                   return
               }
               // 写入策略(保存到文件/数据库)
               e.SavePolicy()
               ctx.String(http.StatusOK, "删除用户成功")
               return
           })
           r.GET("/test", func(ctx *gin.Context) {
               ctx.JSON(http.StatusOK, map[string]interface{}{
                   "sub": ctx.GetHeader("user"),
                   "obj": ctx.Request.URL.Path,
                   "act": ctx.Request.Method,
               })
               return
           })
           r.Run()
       }
  2. 基于数据库:

    1. model.conf

       [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
    2. main.go

       package main
      
       import (
           "fmt"
           "github.com/casbin/casbin/v2"
           gormadapter "github.com/casbin/gorm-adapter/v3"
           "github.com/gin-gonic/gin"
           "gorm.io/driver/mysql"
           "gorm.io/gorm"
           "net/http"
       )
      
       var e *casbin.Enforcer
      
       func init() {
           dsn := "root:123456@tcp(127.0.0.1:3306)/casbin_test?charset=utf8mb4&parseTime=True&loc=Local"
           db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
           if err != nil {
               panic(err)
           }
           adapter, _ := gormadapter.NewAdapterByDB(db)
           e, err = casbin.NewEnforcer("model.conf", adapter)
           if err != nil {
               panic(err)
           }
           // 加载策略(从文件/数据库加载到内存)
           e.LoadPolicy()
       }
      
       func checkPermission(ctx *gin.Context) {
           sub := ctx.GetHeader("user")
           obj := ctx.Request.URL.Path
           act := ctx.Request.Method
           ok, err := e.Enforce(sub, obj, act)
           if err != nil {
               ctx.String(http.StatusInternalServerError, "内部服务器错误")
               ctx.Abort()
           }
           if !ok {
               ctx.String(http.StatusOK, "权限验证不通过")
               ctx.Abort()
           }
           fmt.Println("权限验证通过")
           ctx.Next()
       }
      
       func main() {
           r := gin.Default()
           r.Use(checkPermission)
           // 新增策略
           r.PUT("/policy", func(ctx *gin.Context) {
               sub := ctx.Query("user")
               obj := ctx.Query("path")
               act := ctx.Query("method")
               role := ctx.Query("group")
               if ok, err := e.AddPolicy(sub, obj, act); !ok || err != nil {
                   ctx.String(http.StatusOK, "新增策略失败")
                   return
               }
               if role != "" {
                   if ok, err := e.AddRoleForUser(sub, role); !ok || err != nil {
                       ctx.String(http.StatusOK, "新增策略分组失败")
                       return
                   }
               }
               // 写入策略(保存到文件/数据库)
               e.SavePolicy()
               ctx.String(http.StatusOK, "新增策略成功")
               return
           })
           // 删除策略
           r.DELETE("/policy", func(ctx *gin.Context) {
               sub := ctx.Query("user")
               obj := ctx.Query("path")
               act := ctx.Query("method")
               role := ctx.Query("group")
               if ok, err := e.RemovePolicy(sub, obj, act); !ok || err != nil {
                   ctx.String(http.StatusOK, "删除策略失败")
                   return
               }
               if role != "" {
                   if ok, err := e.DeleteRoleForUser(sub, role); !ok || err != nil {
                       ctx.String(http.StatusOK, "删除策略分组失败")
                       return
                   }
               }
               // 写入策略(保存到文件/数据库)
               e.SavePolicy()
               ctx.String(http.StatusOK, "删除策略成功")
               return
           })
           // 策略列表
           r.GET("/policy", func(ctx *gin.Context) {
               list := e.GetPolicy()
               ctx.JSON(http.StatusOK, list)
               return
           })
           // 删除用户(同时删除【策略】和【分组】)
           r.DELETE("/user", func(ctx *gin.Context) {
               sub := ctx.Query("user")
               // 删除指定用户
               if ok, err := e.DeleteUser(sub); !ok || err != nil {
                   ctx.String(http.StatusOK, "删除用户失败")
                   return
               }
               // 写入策略(保存到文件/数据库)
               e.SavePolicy()
               ctx.String(http.StatusOK, "删除用户成功")
               return
           })
           r.GET("/test", func(ctx *gin.Context) {
               ctx.JSON(http.StatusOK, map[string]interface{}{
                   "sub": ctx.GetHeader("user"),
                   "obj": ctx.Request.URL.Path,
                   "act": ctx.Request.Method,
               })
               return
           })
           r.Run()
       }
文档更新时间: 2024-04-20 10:57   作者:lee