Casbin
是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。
官网:https://casbin.org/docs/zh-CN/rbac-with-domains-api
中文文档:https://casbin.org/docs/zh-CN/overview
RBAC API:https://casbin.org/docs/zh-CN/rbac-api
域内基于角色的访问控制 API:https://casbin.org/docs/zh-CN/rbac-with-domains-api
Casbin
可以:
{subject, object, action}
。RBAC
中的多层角色继承,不止主体可以有角色,资源也可以具有角色。root
或administrator
。超级用户可以执行任何操作而无需显式的权限声明。keyMatch
,方便对路径式的资源进行管理,如 /foo/bar
可以映射到 /foo*
Casbin
不能:
casbin
只负责访问控制。应该有其他专门的组件负责身份认证,然后由casbin
进行访问控制,二者是相互配合的关系。Casbin
认为由项目自身来管理用户、角色列表更为合适, 用户通常有他们的密码,但是Casbin
的设计思想并不是把它作为一个存储密码的容器。 而是存储RBAC
方案中用户和角色之间的映射关系。[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) && r.obj == p.obj && r.act == p.act
[request_definition]
r = sub, dom, obj, act
[policy_definition]
p = sub, dom, obj, act
[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 && r.act == p.act
package casbin
import (
"errors"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
"github.com/casbin/gorm-adapter/v3"
"go.uber.org/zap"
"yt.yin/core/global"
)
// InitCasbin
/**
* @Description: 初始化Casbin执行者(与gorm结合)
* @param DB Gorm连接池
* @param casbinConfPath casbin配置文件地址
* @return Enforcer casbin执行者
* @return err 错误
*/
func InitCasbin(casbinConfPath ...string) (err error) {
// Gorm适配器
adapter, err := gormadapter.NewAdapterByDB(global.DB)
if err != nil {
global.LOG.Error("创建Casbin Gorm适配器错误:", zap.Any("err", err))
return errors.New("Casbin Gorm适配器错误:" + err.Error())
}
global.LOG.Info("创建Casbin Gorm适配器成功")
if len(casbinConfPath) > 0 {
// 通过ORM新建一个执行者
global.Enforcer, err = casbin.NewEnforcer(casbinConfPath[0], adapter)
if err != nil {
global.LOG.Error("新建Casbin执行者异常:", zap.Any("err", err))
return errors.New("新建Casbin执行者异常:" + err.Error())
}
} else {
m, _ := model.NewModelFromString(`
[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) && r.obj == p.obj && r.act == p.act
`)
global.Enforcer, err = casbin.NewEnforcer(m, adapter)
if err != nil {
global.LOG.Error("新建Casbin执行者异常:", zap.Any("err", err))
return errors.New("新建Casbin执行者异常:" + err.Error())
}
}
// 导入访问策略
err = global.Enforcer.LoadPolicy()
if err != nil {
global.LOG.Error("导入访问策略异常:", zap.Any("err", err))
return errors.New("导入访问策略异常:" + err.Error())
}
return nil
}
// 初始化casbin执行者
// Enforcer, casbinErr := casbin.InitCasbin("resources\\rbac_model.conf")
Enforcer, casbinErr := casbin.InitCasbin()
if casbinErr != nil {
panic(casbinErr)
}
global.Enforcer = Enforcer
e.AddRoleForUser("user", "role")
roles := []string{
"role1",
"role2",
"role3",
"role4",
"role5",
}
_, err = Enforcer.AddRolesForUser("user1", roles)
if err != nil {
log.Fatalln("为用户批量添加角色失败")
}
e.DeleteRoleForUser("user", "role")
e.DeleteRolesForUser("user")
res, err := Enforcer.GetRolesForUser("user1")
if err != nil {
log.Fatalln("获取用户角色失败")
} else {
log.Println("用户角色:", res)
}
res := e.GetUsersForRole("role")
res := e.HasRoleForUser("user", "role")
_, err = Enforcer.AddPolicy("role1", "/api/5", "POST")
if err != nil {
log.Fatalln("添加API权限(策略)失败")
} else {
log.Println("添加API权限(策略)成功")
}
rules := [][]string{
{"role1", "/api/1", "POST"},
{"role2", "/api/1", "POST"},
{"role3", "/api/1", "POST"},
{"role1", "/api/2", "POST"},
{"role1", "/api/3", "POST"},
{"role1", "/api/4", "POST"},
{"role1", "/api/5", "POST"},
}
_, err = Enforcer.AddPolicies(rules)
if err != nil {
log.Fatalln("批量添加API权限(策略)失败")
} else {
log.Println("批量添加API权限(策略)成功")
}
_, err = Enforcer.DeletePermissionsForUser("role1")
if err != nil {
log.Fatalln("批量删除API权限(策略)失败")
} else {
log.Println("批量删除API权限(策略)成功")
}
利用字段筛选器查询策略(授权规则)
answer := Enforcer.GetFilteredPolicy(0, "", "/api/4", "POST")
log.Println("answer:", answer)
result := Enforcer.GetPermissionsForUser("role")
log.Println("策略:", result)
result ,err= Enforcer.GetImplicitPermissionsForUser("user")
log.Println("策略:", result)
sub := "user1"
obj := "/api/2"
act := "POST"
ok, err := Enforcer.Enforce(sub, obj, act)
if ok {
fmt.Println("通过权限")
} else || err!=nil {
fmt.Println("权限没有通过")
}
ok, err := e.AddRoleForUserInDomain("用户", "角色", "域")
如果用户已经拥有该角色,则返回false
ok, err := e.DeleteRoleForUserInDomain("用户", "角色", "域")
如果用户没有任何角色,则返回false
rules := [][]string{
{ "role1", "domain1", "www.baidu.com", "GET"},
{ "role2", "domain1", "www.baidu.com", "GET"},
{ "role3", "domain1", "www.baidu.com", "GET"},
{ "role4", "domain1", "www.baidu.com", "GET"},
{ "role5", "domain1", "www.baidu.com", "GET"},
{ "role6", "domain1", "www.baidu.com", "GET"},
{ "role7", "domain1", "www.baidu.com", "GET"},
}
global.Enforcer.AddPolicies(rules)