• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    go语言使用Casbin实现角色的权限控制

    本文主要介绍了go语言使用Casbin实现角色的权限控制,分享给大家,具体如下:

    介绍 Casbin 是什么?

    官方解释:Casbin是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。

    Casbin只负责访问控制。身份认证 authentication(即验证用户的用户名、密码),需要其他专门的身份认证组件负责。例如(jwt-go)

    两个核心概念:

    访问控制模型model和策略policy。

    工作原理:

    Casbin把 访问控制模型 被抽象为基于

    PERM元模型 (Policy, Effect, Request, Matchers) [策略,效果,请求,匹配器], 反映了权限的本质 – 访问控制

    匹配来源:定义的 request 和 存储的 police 比对判断。

    所有 model file 中主要就是定义 PERM 4 个部分的一个文件( model.conf , 这个文件一般是固定的)。

    因此,切换或升级项目的授权机制与修改配置一样简单。 您可以通过组合可用的模型来定制您自己的访问控制模型(ACL, RBAC, ABAC)。

    例如,您可以在一个model中获得RBAC角色和ABAC属性,并共享一组policy规则。

    g, g2, g3 表示不同的 RBAC 体系, _, _ 表示用户和角色 _, _, _ 表示用户, 角色, 域(也就是租户)

    rbac_models.conf

    # Request definition
    [request_definition]
    r = sub, obj, act
    
    # Policy definition
    [policy_definition]
    p = sub, obj, act
    
    # Policy effect
    [policy_effect]
    e = some(where (p.eft == allow))
    
    # Matchers
    [matchers]
    m = r.sub == p.sub  r.obj == p.obj  r.act == p.act
    
    

    实战

    一般运用到项目后台的管理权限中

    初始化数据库

    初始化环境后,系统会在你选择的数据库自动生成一个casbin_rule的数据库表

    用户权限的增删改查

    tips:这些接口,需要放在截器中间件前面, 不然空表无法添加数据

    //使用自定义拦截器中间件
    r.Use(Authorize())
    //增加policy
    	r.POST("/api/v1/add", func(c *gin.Context) {
    		fmt.Println("增加Policy")
    		if ok, _ := Enforcer.AddPolicy("admin", "/api/v1/world", "GET"); !ok {
    			fmt.Println("Policy已经存在")
    		} else {
    			fmt.Println("增加成功")
    		}
    	})
    	//删除policy
    	r.DELETE("/api/v1/delete", func(c *gin.Context) {
    		fmt.Println("删除Policy")
    		if ok, _ := Enforcer.RemovePolicy("admin", "/api/v1/world", "GET"); !ok {
    			fmt.Println("Policy不存在")
    		} else {
    			fmt.Println("删除成功")
    		}
    	})
    	//获取policy
    	r.GET("/api/v1/get", func(c *gin.Context) {
    		fmt.Println("查看policy")
    		list := Enforcer.GetPolicy()
    		for _, vlist := range list {
    			for _, v := range vlist {
    				fmt.Printf("value: %s, ", v)
    			}
    		}
    	})
    

    添加权限,访问其添加接口


    单个用户保存权限的路由是多条记录

    在使用Casbin中间件时,会访问表中的数据库表 ,得到相应的权限信息,增加访问信息后,访问接口成功

    代码

    package main
    
    import (
    	"fmt"
    	"github.com/casbin/casbin"
    	xormadapter "github.com/casbin/xorm-adapter"
    	"github.com/gin-gonic/gin"
    	_ "github.com/go-sql-driver/mysql"
    	"log"
    	"net/http"
    )
    
    var Enforcer *casbin.Enforcer
    
    func init() {
    	CasbinSetup()
    }
    
    // 初始化casbin
    func CasbinSetup(){
    	a, err := xormadapter.NewAdapter("mysql", "root:root123@tcp(127.0.0.1:3306)/casbin?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
    	//return e
    }
    
    
    func Hello(c *gin.Context) {
    	fmt.Println("Hello 接收到GET请求..")
    	c.JSON(http.StatusOK, gin.H{
    		"code": 200,
    		"msg":  "Success",
    		"data": "Hello 接收到GET请求..",
    	})
    }
    
    
    func main() {
    	//获取router路由对象
    	r := gin.New()
    
    
    	//增加policy
    	r.GET("/api/v1/add", func(c *gin.Context) {
    		fmt.Println("增加Policy")
    		if ok, _ := Enforcer.AddPolicy("admin", "/api/v1/world", "GET"); !ok {
    			fmt.Println("Policy已经存在")
    		} else {
    			fmt.Println("增加成功")
    		}
    	})
    	//删除policy
    	r.DELETE("/api/v1/delete", func(c *gin.Context) {
    		fmt.Println("删除Policy")
    		if ok, _ := Enforcer.RemovePolicy("admin", "/api/v1/world", "GET"); !ok {
    			fmt.Println("Policy不存在")
    		} else {
    			fmt.Println("删除成功")
    		}
    	})
    	//获取policy
    	r.GET("/api/v1/get", func(c *gin.Context) {
    		fmt.Println("查看policy")
    		list := Enforcer.GetPolicy()
    		for _, vlist := range list {
    			for _, v := range vlist {
    				fmt.Printf("value: %s, ", v)
    			}
    		}
    	})
    
    	//使用自定义拦截器中间件
    	r.Use(Authorize())
    
    
    
    
    	//创建请求
    	r.GET("/api/v1/hello", Hello)
    	r.Run(":9000") //参数为空 默认监听8080端口
    }
    
    
    
    
    //拦截器
    func Authorize() gin.HandlerFunc {
    
    	return func(c *gin.Context) {
    		//var e *casbin.Enforcer
    		e := Enforcer
    
    		//从DB加载策略
    		e.LoadPolicy()
    
    		//获取请求的URI
    		obj := c.Request.URL.RequestURI()
    		//获取请求方法
    		act := c.Request.Method
    		//获取用户的角色 应该从db中读取
    		sub := "admin"
    
    		//判断策略中是否存在
    		if ok, _ := e.Enforce(sub, obj, act); ok {
    			fmt.Println("恭喜您,权限验证通过")
    			c.Next() // 进行下一步操作
    		} else {
    			fmt.Println("很遗憾,权限验证没有通过")
    			c.Abort()
    		}
    	}
    }

    总代码

    package main
    
    import (
    	"fmt"
    	"github.com/casbin/casbin"
    	xormadapter "github.com/casbin/xorm-adapter"
    	"github.com/gin-gonic/gin"
    	_ "github.com/go-sql-driver/mysql"
    	"log"
    	"net/http"
    )
    
    var Enforcer *casbin.Enforcer
    
    func init() {
    	CasbinSetup()
    }
    
    // 初始化casbin
    func CasbinSetup(){
    	a, err := xormadapter.NewAdapter("mysql", "root:root123@tcp(127.0.0.1:3306)/casbin?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
    	//return e
    }
    
    
    func Hello(c *gin.Context) {
    	fmt.Println("Hello 接收到GET请求..")
    	c.JSON(http.StatusOK, gin.H{
    		"code": 200,
    		"msg":  "Success",
    		"data": "Hello 接收到GET请求..",
    	})
    }
    
    
    func main() {
    	//获取router路由对象
    	r := gin.New()
    
    
    	//增加policy
    	r.GET("/api/v1/add", func(c *gin.Context) {
    		fmt.Println("增加Policy")
    		if ok, _ := Enforcer.AddPolicy("admin", "/api/v1/world", "GET"); !ok {
    			fmt.Println("Policy已经存在")
    		} else {
    			fmt.Println("增加成功")
    		}
    	})
    	//删除policy
    	r.DELETE("/api/v1/delete", func(c *gin.Context) {
    		fmt.Println("删除Policy")
    		if ok, _ := Enforcer.RemovePolicy("admin", "/api/v1/world", "GET"); !ok {
    			fmt.Println("Policy不存在")
    		} else {
    			fmt.Println("删除成功")
    		}
    	})
    	//获取policy
    	r.GET("/api/v1/get", func(c *gin.Context) {
    		fmt.Println("查看policy")
    		list := Enforcer.GetPolicy()
    		for _, vlist := range list {
    			for _, v := range vlist {
    				fmt.Printf("value: %s, ", v)
    			}
    		}
    	})
    
    	//使用自定义拦截器中间件
    	r.Use(Authorize())
    
    
    
    
    	//创建请求
    	r.GET("/api/v1/hello", Hello)
    	r.Run(":9000") //参数为空 默认监听8080端口
    }
    
    
    
    
    //拦截器
    func Authorize() gin.HandlerFunc {
    
    	return func(c *gin.Context) {
    		//var e *casbin.Enforcer
    		e := Enforcer
    
    		//从DB加载策略
    		e.LoadPolicy()
    
    		//获取请求的URI
    		obj := c.Request.URL.RequestURI()
    		//获取请求方法
    		act := c.Request.Method
    		//获取用户的角色 应该从db中读取
    		sub := "admin"
    
    		//判断策略中是否存在
    		if ok, _ := e.Enforce(sub, obj, act); ok {
    			fmt.Println("恭喜您,权限验证通过")
    			c.Next() // 进行下一步操作
    		} else {
    			fmt.Println("很遗憾,权限验证没有通过")
    			c.Abort()
    		}
    	}
    }

    封装后的代码

    package mycasbin
    
    import (
    	"simple-api/mongoose"
    	"github.com/casbin/mongodb-adapter"
    	"github.com/casbin/casbin"
    	"gopkg.in/mgo.v2/bson"
    )
    
    type CasbinModel struct {
    	ID       bson.ObjectId `json:"id" bson:"_id"`
    	Ptype    string        `json:"ptype" bson:"ptype"`
    	RoleName string        `json:"rolename" bson:"v0"`
    	Path     string        `json:"path" bson:"v1"`
    	Method   string        `json:"method" bson:"v2"`
    }
    
    //添加权限
    func (c *CasbinModel) AddCasbin(cm CasbinModel) bool {
    	e := Casbin()
    	e.AddPolicy(cm.RoleName, cm.Path, cm.Method)
    	return true
    
    }
    
    //持久化到数据库
    // "github.com/casbin/mongodb-adapter"
    // func Casbin() *casbin.Enforcer {
    // 	a := mongodbadapter.NewAdapter(mongoose.MongoUrl)
    // 	e := casbin.NewEnforcer("conf/auth_model.conf", a)
    // 	e.LoadPolicy()
    // 	return e
    // }
    func Casbin() *casbin.Enforcer {
    	a := mongodbadapter.NewAdapter(mongoose.MongoUrl)
    	e, err := casbin.NewEnforcer("conf/auth_model.conf", a)
    	if err != nil {
    		panic(err)
    	}
    	e.LoadPolicy()
    	return e
    }
    
    package apis
    
    import (
    	"net/http"
    	"simple-api/utils/mycasbin"
    
    	"github.com/gin-gonic/gin"
    	"gopkg.in/mgo.v2/bson"
    )
    
    var (
    	casbins = mycasbin.CasbinModel{}
    )
    
    func AddCasbin(c *gin.Context) {
    	rolename := c.PostForm("rolename")
    	path := c.PostForm("path")
    	method := c.PostForm("method")
    	ptype := "p"
    	casbin := mycasbin.CasbinModel{
    		ID:       bson.NewObjectId(),
    		Ptype:    ptype,
    		RoleName: rolename,
    		Path:     path,
    		Method:   method,
    	}
    	isok := casbins.AddCasbin(casbin)
    	if isok {
    		c.JSON(http.StatusOK, gin.H{
    			"success": true,
    			"msg":     "保存成功",
    		})
    	} else {
    		c.JSON(http.StatusOK, gin.H{
    			"success": false,
    			"msg":     "保存失败",
    		})
    	}
    }
    

    参考

    https://www.jianshu.com/p/9506406e745f

    到此这篇关于go语言使用Casbin实现角色的权限控制的文章就介绍到这了,更多相关go语言角色权限控制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • Golang之casbin权限管理的实现
    上一篇:Go实现基于RSA加密算法的接口鉴权
    下一篇:浅谈golang package中init方法的多处定义及运行顺序问题
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    go语言使用Casbin实现角色的权限控制 语言,使用,Casbin,实现,角色,