RBAC

RBAC在用户和权限之间引入了“角色(Role)”的概念

用户关联角色,角色关联权限

每个用户关联一个或多个角色,每个角色关联一个或多个权限,从而可以实现了非常灵活的权限管理。角色可以根据实际业务需求灵活创建,这样就省去了每新增一个用户就要关联一遍所有权限的麻烦

casbin相关方法

// 初始化
func (casbinService *CasbinService) Casbin() *casbin.SyncedEnforcer {
   once.Do(func() {
      a, _ := gormadapter.NewAdapterByDB(global.GVA_DB) //设置数据库的表
      syncedEnforcer, _ = 	casbin.NewSyncedEnforcer(global.GVA_CONFIG.Casbin.ModelPath, a)
      //将模型与表关联
   })
   _ = syncedEnforcer.LoadPolicy() //读取策略,加载表的内容
   return syncedEnforcer
}
// 添加策略
e := casbinService.Casbin()
success, _ := e.AddPolicies(rules)//全量策略

// 获取策略
e := casbinService.Casbin()
list := e.GetFilteredPolicy(0, authorityId)

//是否存在权限

模型

### 在官方restful基础上添加了角色组
[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)&& keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)

示例代码

package main

import (
	"fmt"

	"github.com/casbin/casbin/v2"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var (
	syncedEnforcer *casbin.SyncedEnforcer //异步Enforcer,当策略改变时需要重新LoadPolicy
	db             *gorm.DB
)

// ConnDB 数据库链接
func ConnDB(user, password, host string, port int, Dbname string) *gorm.DB {
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, password, host, port, Dbname)
	//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
	db_, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}
	db = db_
	return db
}

// CasbinInit 初始化
func CasbinInit(db *gorm.DB) {
	a, err := gormadapter.NewAdapterByDB(db) //设置数据库的表
	if err != nil {
		panic("NewAdapterByDB, error=" + err.Error())
	}
	syncedEnforcer, err = casbin.NewSyncedEnforcer("./rbac.conf", a)
	if err != nil {
		panic("NewAdapterByDB, error=" + err.Error())
	}
	Casbin()
}

// 获取syncedEnforcer
func Casbin() *casbin.SyncedEnforcer {
	err := syncedEnforcer.LoadPolicy() //读取策略,加载表的内容
	if err != nil {
		panic("LoadPolicy, error=" + err.Error())
	}
	return syncedEnforcer
}

// AddPolicy 添加策略
func AddPolicy(role, path, method string) bool {
	e := Casbin()
	rules := []string{role, path, method}
	success, _ := e.AddPolicy(rules)
	return success
}

// RemovePolicy 删除策略
func RemovePolicy(role, path, method string) bool {
	e := Casbin()
	rules := []string{role, path, method}
	success, _ := e.RemovePolicy(rules)
	return success
}

// GetFilteredPolicy 获取策略
func GetFilteredPolicy(role string) [][]string {
	// 获取策略
	e := Casbin()
	return e.GetFilteredPolicy(0, role) //0就代表v0列,1就代表v1列
}

// Enforce 判断权限
func Enforce(sub, obj, act string) bool {
	e := Casbin()
	success, _ := e.Enforce(sub, obj, act)
	return success
}

func main() {
	ConnDB("root", "zz123456*", "localhost", 3306, "casbin")
	CasbinInit(db)
	e := Casbin()
	AddPolicy("bob", "/api", "(POST)|(GET)") //同时新增多个act
	e.AddRoleForUser("1112", "bob")
	fmt.Println(e.GetPolicy()) //0就代表v0列,1就代表v1列
	fmt.Println(Enforce("1112", "/api", "POST"))
}