基于属性的访问控制
基于属性的访问控制根据属性/值条件授予或拒绝读取或遍历节点或关系的权限。每个基于属性的权限只能由单个属性进行限制。有关这些权限的信息和语法,请参阅读取权限。
使用基于属性的访问控制时,请确保用于规则的属性无法修改。可以更改此属性的用户可能会影响已授予的基于属性的权限。 |
语法
要指定权限的属性/值条件,可以使用以下语法
{GRANT | DENY | REVOKE [GRANT | DENY]}
[IMMUTABLE]
{MATCH | READ | TRAVERSE}
ON { HOME GRAPH | GRAPH[S] { * | name[, ...] } }
[
ELEMENT[S] { * | label-or-rel-type[, ...] }
| NODE[S] { * | label[, ...] }
| RELATIONSHIP[S] { * | rel-type[, ...] }
| FOR {
([var][:label["|" ...]] "{" property: value "}")
| (var[:label["|" ...]])
WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } }
| (var[:label["|" ...]]
WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } )
| ()[<]-"["[var][:type["|" ...]] "{" property: value "}" "]"-[>]()
| ()[<]-"["var[:type["|" ...]]"]"-[>]()
WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } }
| ()[<]-"["var[:type["|" ...]]
WHERE [NOT] var.property { { = | <> | > | >= | < | <= } value | IS NULL | IS NOT NULL | IN { "["[value[, ...]]"]" | listParam } } "]"-[>]()
}
]
{TO | FROM} role[, ...]
性能考量
在某些场景下,添加基于属性的访问控制可能会导致显著的性能开销。有关更详细的信息,请参阅限制。
当存在属性规则时,以下因素可能会加剧对性能的影响
-
相关节点和关系上的属性数量(属性越多 = 性能影响越大)。
-
基于属性的权限数量(基于属性的权限越多 = 性能影响越大)。
-
权限类型:
TRAVERSE
基于属性的权限比READ
基于属性的权限对性能影响更大。 -
正在运行的存储介质类型。通过访问磁盘存储,基于属性的权限对性能的影响会显著放大。
为了减少性能影响,建议使用 block
存储格式,因为它对解析基于属性的权限所需的读取类型进行了更好的优化。
对于性能关键的场景,建议根据标签设计权限。
示例
您可以使用以下语法定义基于属性的权限
GRANT privilege-name ON GRAPH graph-name FOR pattern TO role-name
用户角色无需对基于属性的权限所使用的属性拥有 |
使用另一个属性的值授予特定属性的基于属性的权限
以下示例展示了如何授予角色 regularUsers
权限,以读取 Email
或 Website
节点上域为 exampledomain.com
的 address
属性
GRANT READ { address } ON GRAPH * FOR (n:Email|Website) WHERE n.domain = 'exampledomain.com' TO regularUsers
或者,您可以使用以下语法
GRANT READ { address } ON GRAPH * FOR (:Email|Website {domain: 'exampledomain.com'}) TO regularUsers
以下示例展示了如何授予角色 regularUsers
权限,以读取 classification
等于 UNCLASSIFIED
的 OWNS
关系上的 since
属性
GRANT READ { since } ON GRAPH * FOR ()-[o:OWNS]-() WHERE o.classification = 'UNCLASSIFIED' TO regularUsers
使用 NULL
授予基于属性的权限
以下示例展示了如何授予角色 regularUsers
权限,以遍历标签为 Email
且属性 classification
为 NULL
的节点
GRANT TRAVERSE ON GRAPH * FOR (n:Email) WHERE n.classification IS NULL TO regularUsers
使用比较运算符拒绝基于属性的权限
以下示例展示了如何拒绝角色 regularUsers
权限,以读取和遍历属性 classification
与 UNCLASSIFIED
不同的节点和关系
DENY MATCH {*} ON GRAPH * FOR (n) WHERE n.classification <> 'UNCLASSIFIED' TO regularUsers
DENY MATCH {*} ON GRAPH * FOR ()-[r]-() WHERE r.classification <> 'UNCLASSIFIED' TO regularUsers
使用属性值授予所有属性的基于属性的权限
以下示例展示了如何授予角色 regularUsers
权限,以读取 securityLevel
属性大于 3
的节点和关系上的所有属性
GRANT READ {*} ON GRAPH * FOR (n) WHERE n.securityLevel > 3 TO regularUsers
GRANT READ {*} ON GRAPH * FOR ()-[r]-() WHERE r.securityLevel > 3 TO regularUsers
用户角色 |
使用值列表拒绝基于属性的权限
以下示例展示了如何拒绝权限,以读取 classification
属性不在 [UNCLASSIFIED, PUBLIC]
列表中的所有节点和关系上的所有属性
DENY READ {*} ON GRAPH * FOR (n) WHERE NOT n.classification IN ['UNCLASSIFIED', 'PUBLIC'] TO regularUsers
DENY READ {*} ON GRAPH * FOR ()-[r]-() WHERE NOT r.classification IN ['UNCLASSIFIED', 'PUBLIC'] TO regularUsers
使用时间值授予基于属性的权限
以下示例展示了如何授予权限,以读取 createdAt
属性晚于当前日期的节点和关系上的所有属性
GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date() TO regularUsers
GRANT READ {*} ON GRAPH * FOR ()-[r]-() WHERE r.createdAt > date() TO regularUsers
|
并非所有时间值都可比较,请参阅 Cypher 手册 → 语法 → 运算符 → 值的排序和比较。 |
您可以通过运行以下命令,将上一个示例中通过命令创建的权限显示为撤销命令
SHOW ROLE regularUsers PRIVILEGES AS REVOKE COMMANDS
命令 |
---|
行数: 2 |