go语言web开发系列之十一:gin框架通过casbin实现rbac权限设计(csv存储)

一,安装casbin

1,casbin项目代码的地址

https://github.com/casbin/casbin

2,为go安装casbin

liuhongdi@ku:~$ go get -u github.com/casbin/casbin/v2

说明:刘宏缔的go森林是一个专注golang的博客,
          地址:https://blog.csdn.net/weixin_43881017

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,演示项目的相关信息

1,项目地址

https://github.com/liuhongdi/digv11

2,项目功能说明:

   /admin/* :只有role为 superAdmin时可访问

  /article/* : role为superAdmin/user时均可访问

  /home/*:   role为任何用户时均可访问

3,项目结构:如图:

三,配置文件说明:

1,config/rbac_model.conf

  1.  
    # Request definition 自定义请求的格式
  2.  
    [request_definition]
  3.  
    r = sub, obj, act
  4.  
     
  5.  
    # Policy definition 策略定义
  6.  
    [policy_definition]
  7.  
    p = sub, obj, act
  8.  
     
  9.  
    # Policy effect
  10.  
    [policy_effect]
  11.  
    e = some(where (p.eft == allow))
  12.  
     
  13.  
    # Matchers
  14.  
    [matchers]
  15.  
    #m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
  16.  
    m = (r.sub == p.sub || p.sub == "*") && keyMatch(r.obj,p.obj) && (r.act == p.act || p.act == "*")

2,rbac2.csv

  1.  
    p,superAdmin,/article/*,*
  2.  
    p,superAdmin,/admin/*,*
  3.  
    p,*,/home/*,*
  4.  
    p,user,/article/*,*

说明:csv文件必须用相应的软件生成,如图:

四,go代码说明

1,homeController.go

  1.  
    package controller
  2.  
     
  3.  
    import (
  4.  
    "github.com/gin-gonic/gin"
  5.  
    "github.com/liuhongdi/digv11/pkg/result"
  6.  
    )
  7.  
     
  8.  
    type HomeController struct{}
  9.  
     
  10.  
    func NewHomeController() HomeController {
  11.  
    return HomeController{}
  12.  
    }
  13.  
    //首页,任何人可访问,不登录也可访问
  14.  
    func (a *HomeController) Home(c *gin.Context) {
  15.  
    resultRes := result.NewResult(c)
  16.  
    resultRes.Success("this is home page");
  17.  
    return
  18.  
    }

2,adminController.go

  1.  
    package controller
  2.  
     
  3.  
    import (
  4.  
    "github.com/gin-gonic/gin"
  5.  
    "github.com/liuhongdi/digv11/pkg/result"
  6.  
    )
  7.  
     
  8.  
    type HomeController struct{}
  9.  
     
  10.  
    func NewHomeController() HomeController {
  11.  
    return HomeController{}
  12.  
    }
  13.  
    //首页,任何人可访问,不登录也可访问
  14.  
    func (a *HomeController) Home(c *gin.Context) {
  15.  
    resultRes := result.NewResult(c)
  16.  
    resultRes.Success("this is home page");
  17.  
    return
  18.  
    }

3,ArticleController.go

  1.  
    package controller
  2.  
     
  3.  
    import (
  4.  
    "fmt"
  5.  
    "github.com/gin-gonic/gin"
  6.  
    "github.com/liuhongdi/digv11/pkg/page"
  7.  
    "github.com/liuhongdi/digv11/pkg/result"
  8.  
    "github.com/liuhongdi/digv11/pkg/validCheck"
  9.  
    "github.com/liuhongdi/digv11/request"
  10.  
    "github.com/liuhongdi/digv11/service"
  11.  
    )
  12.  
     
  13.  
    type ArticleController struct{}
  14.  
     
  15.  
    func NewArticleController() ArticleController {
  16.  
    return ArticleController{}
  17.  
    }
  18.  
    //得到一篇文章的详情
  19.  
    func (a *ArticleController) GetOne(c *gin.Context) {
  20.  
    result := result.NewResult(c)
  21.  
    param := request.ArticleRequest{ID: validCheck.StrTo(c.Param("id")).MustUInt64()}
  22.  
    valid, errs := validCheck.BindAndValid(c, &param)
  23.  
    if !valid {
  24.  
    result.Error(400,errs.Error())
  25.  
    return
  26.  
    }
  27.  
     
  28.  
    if (param.ID == 100) {
  29.  
    var z int = 0
  30.  
    var i int = 100 / z
  31.  
    fmt.Println("i:%i",i)
  32.  
    }
  33.  
     
  34.  
    articleOne,err := service.GetOneArticle(param.ID);
  35.  
    if err != nil {
  36.  
    result.Error(404,"数据查询错误")
  37.  
    } else {
  38.  
    result.Success(&articleOne);
  39.  
    }
  40.  
    return
  41.  
    }
  42.  
     

4,global/casbin.go

  1.  
    package global
  2.  
     
  3.  
    import (
  4.  
    "fmt"
  5.  
    "github.com/casbin/casbin/v2"
  6.  
    "log"
  7.  
    "os"
  8.  
    )
  9.  
     
  10.  
    var (
  11.  
    Enforcer *casbin.Enforcer
  12.  
    )
  13.  
     
  14.  
    //创建casbin的enforcer
  15.  
    func SetupCasbinEnforcer() (error) {
  16.  
    dir, _ := os.Getwd()
  17.  
    modelPath := dir + "/config/rbac_model.conf"
  18.  
    csvPath := dir + "/config/rbac2.csv"
  19.  
    fmt.Println("modelPath:"+modelPath);
  20.  
    fmt.Println("csvPath:"+csvPath);
  21.  
    var errC error
  22.  
    Enforcer, errC = casbin.NewEnforcer(modelPath, csvPath)
  23.  
    //fmt.Printf("RBAC test start ") // output for debug
  24.  
    if (errC != nil) {
  25.  
    //fmt.Println(errC)
  26.  
    log.Fatalf("SetupCasbinEnforcer err: %v", errC)
  27.  
    return errC
  28.  
    } else {
  29.  
    Enforcer.EnableLog(true)
  30.  
    return nil
  31.  
    }
  32.  
    }

5,main.go

  1.  
    package main
  2.  
     
  3.  
    import (
  4.  
    "github.com/gin-gonic/gin"
  5.  
    _ "github.com/jinzhu/gorm/dialects/mysql"
  6.  
    "github.com/liuhongdi/digv11/global"
  7.  
    "github.com/liuhongdi/digv11/router"
  8.  
    "log"
  9.  
    )
  10.  
     
  11.  
    //init
  12.  
    func init() {
  13.  
    //setting
  14.  
    err := global.SetupSetting()
  15.  
    if err != nil {
  16.  
    log.Fatalf("init.setupSetting err: %v", err)
  17.  
    }
  18.  
     
  19.  
    //logger
  20.  
    err = global.SetupLogger()
  21.  
    if err != nil {
  22.  
    log.Fatalf("init.SetupLogger err: %v", err)
  23.  
    }
  24.  
     
  25.  
    //access logger
  26.  
    err = global.SetupAccessLogger()
  27.  
    if err != nil {
  28.  
    log.Fatalf("init.SetupAccessLogger err: %v", err)
  29.  
    }
  30.  
     
  31.  
    //casbin
  32.  
    err = global.SetupCasbinEnforcer()
  33.  
    if err != nil {
  34.  
    log.Fatalf("init.SetupCasbinEnforcer err: %v", err)
  35.  
    global.Logger.Fatalf("init.SetupCasbinEnforcer err: %v", err)
  36.  
    }
  37.  
     
  38.  
    //db
  39.  
    err = global.SetupDBLink()
  40.  
    if err != nil {
  41.  
    log.Fatalf("init.SetupLogger err: %v", err)
  42.  
    global.Logger.Fatalf("init.setupDBEngine err: %v", err)
  43.  
    }
  44.  
     
  45.  
    global.Logger.Infof("------应用init结束")
  46.  
    //global.Logger.
  47.  
    }
  48.  
     
  49.  
    func main() {
  50.  
     
  51.  
     
  52.  
    global.Logger.Infof("------应用main函数开始")
  53.  
    //设置运行模式
  54.  
    gin.SetMode(global.ServerSetting.RunMode)
  55.  
    //引入路由
  56.  
    r := router.Router()
  57.  
    //run
  58.  
    r.Run(":"+global.ServerSetting.HttpPort)
  59.  
    }

6,middleware/permission.go

  1.  
    package middleware
  2.  
     
  3.  
    import (
  4.  
    "fmt"
  5.  
    "github.com/gin-gonic/gin"
  6.  
    "github.com/liuhongdi/digv11/global"
  7.  
    "github.com/liuhongdi/digv11/pkg/result"
  8.  
    )
  9.  
     
  10.  
    func PermissionMiddleWare() gin.HandlerFunc {
  11.  
    return func(c *gin.Context) {
  12.  
     
  13.  
    // 请求的path
  14.  
    p := c.Request.URL.Path
  15.  
    // 请求的方法
  16.  
    m := c.Request.Method
  17.  
     
  18.  
    role:="superAdmin"
  19.  
    //role:="user"
  20.  
    //role:="guest"
  21.  
     
  22.  
    fmt.Println("role:"+role)
  23.  
    fmt.Println("path:"+p)
  24.  
    fmt.Println("method:"+m)
  25.  
     
  26.  
    // 检查用户权限
  27.  
    isPass, err := global.Enforcer.Enforce(role, p, m)
  28.  
    if err != nil {
  29.  
    resultRes := result.NewResult(c)
  30.  
    resultRes.Error(2005,err.Error())
  31.  
    return
  32.  
    }
  33.  
    if isPass {
  34.  
    c.Next()
  35.  
    } else {
  36.  
    resultRes := result.NewResult(c)
  37.  
    resultRes.Error(2006,"无访问权限")
  38.  
    return
  39.  
    }
  40.  
    }
  41.  
    }

7,其他相关代码可访问github

五,测试效果

1,middleware/permission.go中,

  role:="guest"

访问:

http://127.0.0.1:8000/home/home

返回:

访问:

http://127.0.0.1:8000/article/getone/2

返回:

访问:

http://127.0.0.1:8000/admin/admin

返回:

2,middleware/permission.go中,

role:="user"

访问:

http://127.0.0.1:8000/home/home

返回:

访问:

http://127.0.0.1:8000/article/getone/2

返回:

访问:

http://127.0.0.1:8000/admin/admin

返回:

3,middleware/permission.go中,

role:="superAdmin"

访问:

http://127.0.0.1:8000/home/home

返回:

访问:

http://127.0.0.1:8000/article/getone/2

返回:

访问:

http://127.0.0.1:8000/admin/admin

返回:

六,查看库的版本:

  1.  
    module github.com/liuhongdi/digv11
  2.  
     
  3.  
    go 1.15
  4.  
     
  5.  
    require (
  6.  
    github.com/gin-gonic/gin v1.6.3
  7.  
    github.com/go-playground/universal-translator v0.17.0
  8.  
    github.com/go-playground/validator/v10 v10.2.0
  9.  
    github.com/jinzhu/gorm v1.9.16
  10.  
    github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f
  11.  
    github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect
  12.  
    github.com/magiconair/properties v1.8.4 // indirect
  13.  
    github.com/mitchellh/mapstructure v1.3.3 // indirect
  14.  
    github.com/pelletier/go-toml v1.8.1 // indirect
  15.  
    github.com/pkg/errors v0.9.1 // indirect
  16.  
    github.com/spf13/afero v1.4.1 // indirect
  17.  
    github.com/spf13/cast v1.3.1 // indirect
  18.  
    github.com/spf13/jwalterweatherman v1.1.0 // indirect
  19.  
    github.com/spf13/pflag v1.0.5 // indirect
  20.  
    github.com/spf13/viper v1.7.1
  21.  
    github.com/casbin/casbin/v2 v2.17.0
  22.  
    go.uber.org/multierr v1.6.0 // indirect
  23.  
    go.uber.org/zap v1.16.0
  24.  
    golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
  25.  
    golang.org/x/text v0.3.4 // indirect
  26.  
    gopkg.in/ini.v1 v1.62.0 // indirect
  27.  
    gopkg.in/yaml.v2 v2.3.0 // indirect
  28.  
    )
原文地址:https://www.cnblogs.com/ExMan/p/14312240.html