对象访问控制¶
服务端支持以设置访问规则和显式授予权限两种方式管理用户组和用户对特定对象的访问。
访问规则¶
访问规则是一个 JSON 对象,结构化地描述了判断用户或用户组是否具有访问特定对象的权限的方法。访问规则的格式对于目录和文档都是一致的。
仅当用户及其所属的全部用户组都不存在针对目标对象有效的显式授予的权限时,才会执行访问规则检查。访问规则与特定对象(文档或目录)的特定操作类型(读、写、移动和管理)关联,并对正在尝试访问目标对象的用户进行判断。
值得注意的是,当进行访问规则检查时,服务端除检查与当前操作类型相关联的规则之外,还会同时检查作为该操作类型的前置条件的其他操作类型的规则。下面列出了各个操作类型实际会检查的访问规则:
| 操作类型 | 将检查哪些操作类型关联的访问规则 |
|---|---|
读(read) |
读 |
写(write) |
读和写 |
移动(move) |
移动 |
管理(manage) |
读和管理 |
格式¶
一个访问规则应仅包含以下的字段:
| 字段 | 类型 | 描述 |
|---|---|---|
match |
string | 外层匹配模式,值为 "all" 或 "any"。 |
match_groups |
array | 含有零个或多个子匹配组的数组。每个子匹配组也是一个 JSON 对象。 |
一个子匹配组至多包含下列的字段:
| 字段 | 类型 | 描述 |
|---|---|---|
match |
string | 匹配模式,值为 "all" 或 "any"。 |
rights |
object | 描述要匹配的权限及匹配时的模式。 |
groups |
object | 描述要匹配的用户组及匹配时的模式。 |
rights 和 groups 对象的结构:
| 字段 | 类型 | 描述 |
|---|---|---|
match |
string | 匹配模式,值为 "all" 或 "any"。 |
require |
array | 包含要匹配的权限或组名的数组。 |
匹配逻辑¶
为了方便地进行描述,我们规定,一条访问规则所含的全部对象(包括其自身)构成一个匹配树,称构成该树的对象为树的结点,访问规则本身为树的根结点,并称直属于根结点的结点为它的子结点,根结点是这些结点的父结点。
我们同时规定,没有子结点的结点为匹配树的叶结点。
结点的深度由其抵达根结点所需经过的结点的最小数目决定(不含起始结点,但含根结点)。例如,将 match_groups 数组中的子匹配组作为结点,从它们出发,抵达根结点所需要通过的最小结点数量为 1,因此这些子匹配组的深度均为 1。
无论出现在一个匹配树的哪一层级,match 字段都决定了在它所在层级下要以何种模式匹配该结点所规定的条件。
当服务端检查一条访问规则时,它将总是从匹配树的叶结点开始检查。如下所示:
{
"match": "all",
"match_groups": [
{
"match": "all",
"groups": {
"match": "all",
"require": ["sysop", "group1"]
},
"rights": {
"match": "any",
"require": ["oversight", "manage_system"]
}
}
]
}
在本例中,groups 和 rights 是匹配树的叶结点,它们在绝大多数情况下也同样将是一个匹配树的叶结点。
由于 match 被指定为 all,服务端将判断用户是否同时属于 require 字段下数组中所描述的全部用户组,如果情况并非如此,则 groups 结点的检查结果为假;对于 rights 而言,由于 match 被指定为 any,只要用户拥有 require 字段下数组中所描述的任意一个权限,该结点的检查结果即为真。
仅当两个结点的检查结果均为真时,它们共同的父节点的检查结果才为真,因为该节点的 match 字段的值也为 all。
注意空的 require 数组可能引发的意外结果
当 groups 或 rights 结点下的 require 数组为空,即没有对用户所属的用户组或其持有的权限提出任何要求时,服务端并不会忽略该结点的存在,而根据匹配逻辑,由于要求为空,则无论 match 的模式被指定为 all 还是 any,结点的检查结果都将直接返回为真。
若不注意这一可能与直觉相悖的结果,编制的访问规则可能造成意外的权限逃逸。如果您不打算在该结点下检查用户组或权限,请不要定义与其对应的字段。
访问规则的嵌套设计
您可能注意到,访问规则并非被设计为允许无限嵌套的模式。这是由于通过继续嵌套所能实现的效果被认为均可在当前的设计下找到等效的替代。
显式授予权限¶
除了利用访问规则来对尝试访问对象的用户进行统一检查,也可以为特定的用户和用户组显式授予对特定对象执行特定操作的权限。在授予权限时,可以一并指定授权的起止时间。
授权的开始时间是必需的。结束时间若不指定,则授权默认永不过期。