Casbin是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型,支持RBAC中的多层角色继承,不止主体可以有角色,资源也可以具有角色。
RBAC 的三个主要规则:
- 角色分配:只有当主体选择或被分配角色时,主体才能行使权限。
- 角色授权:主体的主动角色必须经过主体的授权。通过上面的规则 1,此规则可确保用户只能承担其被授权的角色。
- 权限授权:只有对主体的主动角色进行了授权,主体才能行使该权限。通过规则 1 和 2,此规则可确保用户只能行使他们被授权的权限。
还可以应用附加约束,并且可以将角色组合在层次结构中,其中较高级别的角色包含子角色拥有的权限。
借助角色层次结构和约束的概念,我们可以控制RBAC来创建或模拟基于网格的访问控制(LBAC)。因此RBAC可以被认为是LBAC的超集。
定义 RBAC 模型时的约定
S = 主体 = 人或自动代理
R = 角色 = 定义权限级别的工作职能或头衔
P = 权限 = 对资源访问模式的批准
SE = 会话 = 涉及 S、R 和/或 P 的映射
SA = 科目分配
PA = 权限分配
RH = 部分排序的角色层次结构。 RH 也可以写成: ≥ (记法:x ≥ y 表示x 继承了y 的权限。)
一个主题可以有多个角色。
一个角色可以有多个主题。
一个角色可以有多个权限。
一个权限可以分配给多个角色。
一个操作可以分配多个权限。
一个权限可以分配给许多操作。
约束对来自相反角色的权限的潜在继承设置了限制性规则。因此它可以用来实现适当的职责分离。例如,不应允许同一个人同时创建登录帐户和授权帐户创建。
如何创建RBAC模型?
Casbin配置文件(Model 文件)
[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
创建支持多租户的RBAC模型:
[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
初始化casbin
package casbinimport ("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
}