基于属性的访问控制

基于属性的访问控制根据属性/值的条件来授予或拒绝读取或遍历节点或关系的权限。每个基于属性的权限只能由单个属性进行限制。有关这些权限语法的详细信息,请参阅 读取权限

使用基于属性的访问控制时,请确保用于规则的属性不可更改。能够更改此属性的用户可能会影响所授予的基于属性的权限。

分片属性数据库不支持基于属性的访问控制。

语法

要指定权限的属性/值条件,可以使用以下语法

{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

用户角色不需要拥有基于属性的权限所使用的属性的 READ 权限。

使用另一个属性的值授予特定属性上的基于属性的权限

以下示例展示了如何向 regularUsers 角色授予对 EmailWebsite 节点(域名为 exampledomain.com)上 address 属性的 READ 权限

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 角色授予对 OWNS 关系(其 classification 等于 UNCLASSIFIED)上 since 属性的 READ 权限

GRANT READ { since } ON GRAPH * FOR ()-[o:OWNS]-() WHERE o.classification = 'UNCLASSIFIED' TO regularUsers

使用 NULL 授予基于属性的权限

以下示例展示了如何向 regularUsers 角色授予对标签为 Emailclassification 属性为 NULL 的节点的 TRAVERSE 权限

GRANT TRAVERSE ON GRAPH * FOR (n:Email) WHERE n.classification IS NULL TO regularUsers

使用比较运算符拒绝基于属性的权限

以下示例展示了如何向 regularUsers 角色拒绝对 classification 属性不等于 UNCLASSIFIED 的节点和关系的 READTRAVERSE 权限

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 的节点和关系的所有属性的 READ 权限

GRANT READ {*} ON GRAPH * FOR (n) WHERE n.securityLevel > 3 TO regularUsers
GRANT READ {*} ON GRAPH * FOR ()-[r]-() WHERE r.securityLevel > 3 TO regularUsers

regularUsers 角色不需要拥有基于属性的权限所使用的 securityLevel 属性的 READ 权限。

使用值列表拒绝基于属性的权限

以下示例展示了如何拒绝 classification 属性不在 [UNCLASSIFIED, PUBLIC] 列表中的节点和关系的所有属性的 READ 权限

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 属性晚于当前日期的节点和关系的所有属性的 READ 权限

GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt > date() TO regularUsers
GRANT READ {*} ON GRAPH * FOR ()-[r]-() WHERE r.createdAt > date() TO regularUsers

date() 函数会被求值,用于评估权限的值是创建该基于属性的权限时的日期。设计属性规则时请记住这一点,并使用 SHOW PRIVILEGES AS COMMANDS 命令查看存储的值。在撤销包含已求值函数(如 date())的基于属性的权限时,这一点至关重要。

并非所有时间值都可以比较,请参阅 Cypher 手册 → 值类型的相等性、排序和比较

您可以通过运行以下命令,将上一个示例中创建的权限显示为撤销命令

SHOW ROLE regularUsers PRIVILEGES AS REVOKE COMMANDS
表 1. 结果
command(命令)

REVOKE GRANT READ {*} ON GRAPH * FOR (n) WHERE n.createdAt  date('2024-10-25') FROM `regularUsers`

REVOKE GRANT READ {*} ON GRAPH * FOR ()-[r]-() WHERE r.createdAt  date('2024-10-25') FROM `regularUsers`

行:2