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

介绍 casbin 是什么?

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

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

两个核心概念:

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

工作原理:

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

perm元模型 (policy, effect, request, matchers) [策略,效果,请求,匹配器], 反映了权限的本质 – 访问控制

  • policy: 定义权限的规则
  • effect: 定义组合了多个 policy 之后的结果, allow/deny
  • request: 访问请求, 也就是谁想操作什么
  • matcher: 判断 request 是否满足 policy

匹配来源:定义的 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":     "保存失败",
		})
	}
}

参考

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