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的简单使用,详情请参考官方文档