RBAC权限控制(GO-casbin)

casbin官方文档:Overview · Casbin

casbin是一个规则的管理(角色拥有哪些权限、用户拥有哪些角色),实现了较为难管理的规则模块。用户、角色、权限三个具体的角色需要应用自己管理

依赖:

"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
"github.com/casbin/gorm-adapter/v3"
"github.com/go-sql-driver/mysql"

Demo

package main

import (
	"fmt"
	"github.com/casbin/casbin/v2"
	casbinmodel "github.com/casbin/casbin/v2/model"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
)

func main() {
	//策略配置
	text := `
[request_definition]
r = sub, obj
[policy_definition]
p = sub, obj
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj || r.sub == "admin"
`
	m, _ := casbinmodel.NewModelFromString(text)
	//从DB获取权限
	orm, err := gormadapter.NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/rbac?charset=utf8", true)
	if err != nil {
		fmt.Printf("gormadapter init error:%s", err.Error())
		return
	}
	//e := casbin.NewEnforcer("./rbac/rbac_models.conf", orm)
	e, err := casbin.NewEnforcer(m, orm)
	if err != nil {
		fmt.Printf("casbin NewEnforcer error:%s", err.Error())
		return
	}
	e.EnableLog(true)
	//添加角色权限
	//e.AddPolicy("admin", "create_user")
	//
	批量添加角色权限
	//polices := make([][]string, 0, 2)
	//polices = append(polices, []string{"admin", "delete_user"})
	//polices = append(polices, []string{"admin", "update_user"})
	//e.AddPolicies(polices)

	查询角色权限
	//ret := e.GetPermissionsForUser("admin")
	//fmt.Println(ret)

	删除角色(相关权限、用户全部删除)
	//ret, err := e.DeleteRole("admin")
	//fmt.Println(ret)

	添加用户角色
	//ret, _ := e.AddGroupingPolicy("zhangsan", "admin")
	//fmt.Println(ret)

	//批量添加用户角色
	//polices := make([][]string, 0, 2)
	//polices = append(polices, []string{"zhangsan", "customer"})
	//polices = append(polices, []string{"zhangsan", "sale"})
	//ret, _ := e.AddGroupingPolicies(polices)
	//fmt.Println(ret)

	//查询用户角色
	//ret, _ := e.GetRolesForUser("zhangsan")
	//fmt.Println(ret)

	用户是否具有某个角色
	//ret, _ := e.HasRoleForUser("zhangsan", "admin")
	//fmt.Println(ret)

	//删除用户(同删除角色)
	//ret, err := e.DeleteUser("zhangsan")
	//fmt.Println(ret)

	//验证是否具有权限
	//ret, err := e.Enforce("zhangsan", "create_user")
	//fmt.Println(ret)
}

casbin支持超级管理员角色校验,即超级管理员拥有系统的全部权限

func newCasbin() *casbin.Enforcer {
	text := `
[request_definition]
r = sub, obj

[policy_definition]
p = sub, obj

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj || checkSuperAdmin(r.sub, "superadmin")
`
	m, _ := casbinmodel.NewModelFromString(text)
	dbConn := "" //数据库连接
	orm, err := gormadapter.NewAdapter("mysql", dbConn, true)
	if err != nil {
		fmt.Printf("gormadapter init error:%s\n", err.Error())
		return nil
	}
	e, err := casbin.NewEnforcer(m, orm)
	if err != nil {
		fmt.Printf("casbin NewEnforcer error:%s\n", err.Error())
		return nil
	}
	//注册超级管理员权限判断
	e.AddFunction("checkSuperAdmin", func(arguments ...interface{}) (interface{}, error) {
		username := arguments[0].(string)
		role := arguments[1].(string)
		// 检查用户名的角色是否为superadmin
		return e.HasRoleForUser(username, role)
	})

	e.EnableLog(true)

	return e
}

casbin支持多个系统的规则配置

规则如下:

[request_definition]
r = sub, dom, obj

[policy_definition]
p = sub, dom, obj

[role_definition]
g = _, _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj || checkSuperAdmin(r.sub, "superadmin")

使用示例

package rbac

import (
	"fmt"
	"github.com/casbin/casbin/v2"
	casbinmodel "github.com/casbin/casbin/v2/model"
	gormadapter "github.com/casbin/gorm-adapter/v3"
)

// RbacDomain 支持多业务(domain)的casbin包
type RbacDomain struct {
	enforcer *casbin.Enforcer
	domain   string
}

func NewDomainWithGorm(text, domain, dbConn string) (ret *RbacDomain, err error) {
	m, _ := casbinmodel.NewModelFromString(text)
	orm, err := gormadapter.NewAdapter("mysql", dbConn, true)
	if err != nil {
		fmt.Printf("gormadapter init error:%s\n", err.Error())
		return
	}
	e, err := casbin.NewEnforcer(m, orm)
	if err != nil {
		fmt.Printf("casbin NewEnforcer error:%s\n", err.Error())
		return
	}
	//注册超级管理员权限判断
	e.AddFunction("checkSuperAdmin", func(arguments ...interface{}) (interface{}, error) {
		username := arguments[0].(string)
		role := arguments[1].(string)
		// 检查用户名的角色是否为超级管理员
		return e.HasRoleForUser(username, role, domain)
	})

	e.EnableLog(true)
	ret = &RbacDomain{
		enforcer: e,
		domain:   domain,
	}
	return
}

// AddRoleForUser 添加用户角色
func (c *RbacDomain) AddRoleForUser(username, role string) (bool, error) {
	return c.enforcer.AddRoleForUser(username, role, c.domain)
}

// DeleteRoleForUser 删除用户角色
func (c *RbacDomain) DeleteRoleForUser(username, role string) (bool, error) {
	return c.enforcer.DeleteRoleForUser(username, role, c.domain)
}

// GetUserRoles 获取用户角色
func (c *RbacDomain) GetUserRoles(username string) ([]string, error) {
	return c.enforcer.GetRolesForUser(username, c.domain)
}

// GetRoleUsers 获取角色下的用户
func (c *RbacDomain) GetRoleUsers(role string) ([]string, error) {
	return c.enforcer.GetUsersForRole(role, c.domain)
}

// AddRoleForUserMulti 添加用户角色-批量
func (c *RbacDomain) AddRoleForUserMulti(username string, roles []string) (bool, error) {
	return c.enforcer.AddGroupingPolicies(c.formatMulti(username, roles))
}

// DeleteRoleForUserMulti 删除用户角色-批量
func (c *RbacDomain) DeleteRoleForUserMulti(username string, roles []string) (bool, error) {
	return c.enforcer.RemoveGroupingPolicies(c.formatMulti(username, roles))
}

// UpdateRoleForUserMulti 批量更新用户角色
func (c *RbacDomain) UpdateRoleForUserMulti(username string, roles []string) (bool, error) {
	//删除旧角色
	_, err := c.enforcer.DeleteRolesForUser(username, c.domain)
	if err != nil {
		return false, err
	}
	//添加新角色
	return c.enforcer.AddGroupingPolicies(c.formatMulti(username, roles))
}

// DeleteUser 删除用户:用户的权限一并删除
func (c *RbacDomain) DeleteUser(user string) (bool, error) {
	var err error
	ret1, err := c.enforcer.RemoveFilteredGroupingPolicy(0, user, "", c.domain)
	if err != nil {
		return ret1, err
	}
	ret2, err := c.enforcer.RemoveFilteredPolicy(0, user, "", c.domain)
	return ret1 || ret2, err
}

// DeleteRole 删除角色:角色下的用户和权限一并删除
func (c *RbacDomain) DeleteRole(role string) (bool, error) {
	var err error
	ret1, err := c.enforcer.RemoveFilteredGroupingPolicy(1, role, c.domain)
	if err != nil {
		return ret1, err
	}
	ret2, err := c.enforcer.RemoveFilteredPolicy(0, role, "", c.domain)
	return ret1 || ret2, err
}

// AddPermission 添加角色or用户权限
func (c *RbacDomain) AddPermission(username, permission string) (bool, error) {
	return c.enforcer.AddPermissionForUser(username, permission, c.domain)
}

// AddPermissionMulti 添加角色or用户权限-批量
func (c *RbacDomain) AddPermissionMulti(username string, permissions []string) (bool, error) {
	return c.enforcer.AddPolicies(c.formatMulti(username, permissions))
}

// DeletePermission 删除角色or用户权限
func (c *RbacDomain) DeletePermission(username, permission string) (bool, error) {
	return c.enforcer.DeletePermissionForUser(username, permission, c.domain)
}

// DeletePermissionMulti 删除角色or用户权限-批量
func (c *RbacDomain) DeletePermissionMulti(username string, permissions []string) (bool, error) {
	return c.enforcer.RemovePolicies(c.formatMulti(username, permissions))
}

// GetPermissionsForRole 获取角色权限
func (c *RbacDomain) GetPermissionsForRole(role string) []string {
	list := c.enforcer.GetFilteredNamedPolicy("p", 0, role, "", c.domain)
	ret := make([]string, 0, len(list))
	for _, v := range list {
		ret = append(ret, v[1]) //TODO 权限目前取第二位
	}
	return ret
}

// UpdatePermissionsForRoleMulti 更新角色权限-批量
func (c *RbacDomain) UpdatePermissionsForRoleMulti(role string, polices []string) (ret bool, err error) {
	//删除角色所有权限
	ret, err = c.enforcer.RemoveFilteredPolicy(0, role, "", c.domain)
	if err != nil {
		return
	}
	//添加角色权限
	ret, err = c.enforcer.AddPolicies(c.formatMulti(role, polices))
	return
}

// RemovePolice 删除指定权限
func (c *RbacDomain) RemovePolice(police string) (bool, error) {
	return c.enforcer.RemoveFilteredPolicy(1, police, c.domain)
}

// HasPermission 用户or角色是否具有某权限
func (c *RbacDomain) HasPermission(user, permission string) (bool, error) {
	return c.enforcer.Enforce(user, permission, c.domain)
}

// GetEnforcer 返回 *casbin.Enforcer,用来执行casbin原生方法
func (c *RbacDomain) GetEnforcer() *casbin.Enforcer {
	return c.enforcer
}

func (c *RbacDomain) formatMulti(username string, polices []string) [][]string {
	policeArr := make([][]string, 0, len(polices))
	for _, v := range polices {
		policeArr = append(policeArr, []string{username, v, c.domain})
	}
	return policeArr
}

以上是对casbin-go的简单使用,详情请参考官方文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值