在Casbin中,访问控制模型被抽象为基于PERM元模型(策略,效果,请求,匹配器)的CONF文件。 为项目切换或升级授权机制就像修改配置一样简单。 您可以通过组合可用模型来定制自己的访问控制模型。
PERM模型由四个基础部分组成:策略[Policy],效果[Effect],请求[Request]和匹配器[Matcher]。 这些基础部分描述了资源和用户之间的关系。
定义请求参数。 基本请求是一个元组对象,至少需要一个主体(被访问实体),对象(被访问资源)和动作(访问方法)。
例如,请求定义可能看起来像这样:r={sub,obj,act}
大致意思就是 主体[sub]发送了一个对某个资源[obj]实行[act]操作的请求
定义访问策略的模型。 它指定了策略规则文档中字段的名称和顺序。
例如:p={sub, obj, act} 或 p={sub, obj, act, eft}
注意:如果未定义eft(策略结果),则不会读取策略文件中的结果字段,匹配策略结果将默认允许(allow)。
大致意思就是我们定义了一系列的规则,即某些主体[sub]是否可以[eft]对某些资源[obj]实行[act]操作
定义请求和策略的匹配规则。
例如:m = r.sub == p.sub && r.act == p.act && r.obj == p.obj 这个简单而常见的匹配规则意味着,如果请求的参数(实体,资源和方法)等于策略中找到的那些,那么返回策略结果(p.eft)。 策略的结果将保存在p.eft中。
这个意思就是,Matcher用于判断一个请求是否符合某条策略规则。当你发起一个访问请求时,Casbin 会把这个请求和所有的策略一一对比,通过 Matcher 判断是否有一条策略满足当前请求条件, 举个例子: 🏢 公司权限控制系统:Matcher 例子讲解(优化版) 在一家公司中,存在两个文件资源:
data1:普通资料data2:敏感资料
✅ 权限策略如下(Policy):
员工(employee)可以查看 data1
经理(manager)可以查看 data1
经理(manager)可以查看 data2
👩💼 公司里有两个人:data2(即添加了一个针对小明的特殊策略)
❓现在的问题
我们想判断请求:“小明可以查看 data2 吗?” 🧠 结论 小明可以访问 data2,因为他被直接授权了这条权限策略。 而这个匹配成功是因为:
r.sub == p.sub 成立(小明 == 小明)r.obj == p.obj 成立(data2)r.act == p.act 成立(read)对匹配器的匹配结果进行逻辑组合判断。
例如:e = some(where(p.eft == allow))
这个语句意味着,如果匹配策略结果p.eft有(一些)允许的结果,那么最终结果为真。
那我们接着上面的例子 🧨 如果加一条 deny 策略会怎样? 员工不能查看data2 显然匹配了多条规则
e = some(where(p.eft == allow))对匹配器的匹配结果进行逻辑组合判断,即只要有一个规则是允许(allow),我们就认为最终结果为真显然匹配的规则中有一条是允许的,所以我们认为结果为小明可以查看data2
Casbin中最基本和最简单的模型是ACL。 ACL的模型CONF如下
ACL模型的一个示例策略为:
这意味着:
alice可以读取data1
bob可以写入data2
简单来说就是ACL直接从个体的角度来规定,哪些人可以有哪些权限 还是接着上面的例子,转换成ACL就是
在 Casbin 中,RBAC 是在 ACL 基础上发展出来的一种模型。 它的核心思想是:
不再直接给“个体用户”分配权限,而是先定义“角色”,然后把权限分配给角色,再把用户分配到角色中。 其实基本就是我们例子那样,但还是有不同的
注意到我们例子中有一个特殊的地方,就是我们单独给小明写了一条规则
这是一个直接给用户的权限,即所谓的 个体特权
这种做法是 Casbin 支持的 RBAC-with-ACL 混合模型,所以我们的例子并不是严格意义上的RBAC模型
那我们直接看看我们之前的例子的严格定义
📄 model.conf
✅ 说明:
r = sub, obj, act:请求包括:谁、访问什么、用什么操作。p = sub, obj, act:策略规则,sub 可以是用户或角色。g = _, _:用户和角色之间的关系。e = some(where (p.eft == allow)):只要匹配到一条允许规则,就通过。matchers 中 (g(r.sub, p.sub) || r.sub == p.sub):
其实RBAC有一些变种
这里我只简单讲讲,难免复制粘贴😋
有时,您希望具有特定模式的某些主题、对象或域/租户自动被授予角色。 RBAC中的模式匹配函数可以帮助您做到这一点。
我们知道,通常RBAC在匹配器中表示为 g(r.sub, p.sub)。 然后我们可以使用像这样的策略:
所以 alice 可以阅读所有书籍,包括 book 1 和 book 2。 但可能有数千本书,将每本书都添加到书籍角色(或组)中是非常繁琐的,每个 g 策略规则都需要添加一本书。
但是,使用模式匹配函数,您只需要用一行代码就可以编写策略:
这个总的来说就是使用模式匹配来归结一些相似的资源,比如上面类似的Path可以使用模式匹配归结为一组,其实上面也可以使用通配符,即/book/*,感觉更简单直观
Casbin中的RBAC角色可以是全局的或特定于域的。 特定于域的角色意味着当用户在不同的域/租户中时,用户的角色可以不同。 对于像云这样的大型系统,这非常有用,因为用户通常在不同的租户中。
这里要提及一下,Casbin中还有个概念叫域,其实就类似于namespace这种 与域/租户的角色定义应该如下所示:
第三个_代表域/租户的名称,这部分不应该改变。 然后策略可以是:
这意味着tenant1中的admin角色可以读取data1。 并且alice在tenant1中拥有admin角色,在tenant2中拥有user角色。 因此,她可以读取data1。 然而,由于alice在tenant2中不是admin,她无法读取data2。 然后,在匹配器中,你应该按照以下方式检查角色:
ABAC代表基于属性的访问控制。 它允许你通过使用主体、对象或行为的属性(属性)来控制访问,而不是使用字符串值本身。 你可能听说过一种复杂的ABAC访问控制语言,叫做XACML。 另一方面,Casbin的ABAC要简单得多。 在Casbin的ABAC中,你可以使用结构体或类实例代替模型元素的字符串。 让我们来看一下官方的ABAC示例:
在匹配器中,我们使用r.obj.Owner代替r.obj。 传递给Enforce()函数的r.obj将是一个结构体或类实例,而不是一个字符串。 Casbin将使用反射来为你检索该结构体或类中的obj成员变量。 这是r.obj结构体或类的定义:
✅ 场景还原一下 你想让访问权限不是靠“预先设定的规则”,而是“资源本身的属性”来判断。 比如: 你不想写一堆:
而是直接根据资源里的属性判断: 如果某份资源的 owner == 当前请求人,就让他访问。
你传入的 obj 是一个结构体(或者类),而不是字符串!
可以使用gorm,惊不惊喜😁
具体的使用可以去官网看https://casbin.org/zh/docs/overview 其实使用Casbin最大的障碍就是它的那些概念,理解后,使用反而很简单