授权
这是 GraphQL Library 版本 7 的文档。对于长期支持 (LTS) 版本 5,请参阅 GraphQL Library 版本 5 LTS。 |
授权规则规定了生成的 Cypher 查询可以访问哪些特定数据。它们使用谓词来评估由 GraphQL 查询生成的 Cypher 访问的数据,从而允许或禁止在节点及其属性的上下文中执行。
所有授权规则都隐含地要求进行身份验证,因为这些规则通常是根据 JWT 有效负载中的值进行评估的。
在显式身份验证的情况下(使用 @authentication
指令配置),它仅在 Cypher 翻译时进行评估。需要身份验证的未经验证的请求永远不会到达数据库。
|
筛选规则
筛选规则过滤掉用户无权访问的数据,而不会抛出任何错误。这些规则被转换为筛选谓词,它们根据数据库中匹配的数据进行评估。
此类规则的筛选器的工作方式与查询和聚合的筛选器相同。请参阅 筛选。
筛选规则不仅可以保护数据,还可以向未经授权的用户模糊该数据存在的信息。
例如,以下是如何筛选出不属于当前 User
的 Post
节点
type User @node {
id: ID!
}
type Post @node @authorization(filter: [
{ where: { node: { authors: { some: { id: { eq: "$jwt.sub" } } } } } }
]) {
title: String!
content: String!
authors: [User!]! @relationship(type: "AUTHORED", direction: IN)
}
操作
可以配置筛选仅在某些操作上执行
-
读取
-
聚合
-
更新
-
删除
-
创建关系
-
删除关系
例如,如果仅要求对帖子进行读取和聚合的筛选
type Post @node @authorization(filter: [
{ operations: [READ, AGGREGATE], where: { node: { author: { id: { eq: "$jwt.sub" } } } } }
]) {
title: String!
content: String!
authors: [User!]! @relationship(type: "AUTHORED", direction: IN)
}
如果 |
验证规则
如果查询执行的数据用户无权访问,则验证规则将抛出错误。这些规则通过包含对 apoc.util.validatePredicate
调用 的筛选谓词在数据库中进行评估。
例如,以下是如何在 User
被除用户本人或管理员之外的任何人访问时抛出错误
type JWT @jwt {
roles: [String!]!
}
type User @node @authorization(validate: [
{ where: { node: { id: { eq: "$jwt.sub" } } } }
{ where: { jwt: { roles: { includes: "admin" } } } }
]) {
id: ID!
}
操作
可以配置验证仅在某些操作上执行
-
读取
-
聚合
-
创建
-
更新
-
删除
-
创建关系
-
删除关系
例如,如果仅要求对帖子的更新或删除进行验证
type Post @node @authorization(validate: [
{
operations: [UPDATE, DELETE]
where: { node: { authors: { some: { id: { eq: "$jwt.sub" } } } } }
}
]) {
title: String!
content: String!
authors: [User!]! @relationship(type: "AUTHORED", direction: IN)
}
如果 |
时机
可以配置验证仅在操作执行之前或之后执行。这通过使用接受以下值数组的 when
参数来完成
-
之前
-
之后
此外,有些操作仅支持在它们之前或之后进行验证,下表对此进行了总结
操作 |
时机 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
举例来说,假设您希望某人能够更新帖子。如果您想在更新后检查帖子的作者是否仍是当前用户,请执行以下操作
type Post @node @authorization(validate: [
{ operations: [UPDATE], when: [AFTER], where: { node: { author: { id: "$jwt.sub" } } } }
]) {
title: String!
content: String!
author: User! @relationship(type: "AUTHORED", direction: IN)
}
字段上的授权
@authorization
指令可用于对象类型或其字段,本页面的大多数示例都使用了前者。当应用于字段时,仅当在该字段上执行匹配操作时才会评估授权规则。例如,考虑一个带有 password
字段的 User
类型
type User @node {
id: ID!
username: String!
password: String! @authorization(where: [{ operations: [READ, UPDATE], where: { node: { id: "$jwt.sub" } } }])
}
执行以下查询时,不需要有效的身份
{
users {
username
}
}
但是,请考虑以下查询
{
users {
username
password
}
}
这将要求请求中提供有效的 JWT,并且匹配的用户将根据 JWT 主体进行筛选。尝试更新 password
字段也适用同样的情况,更新将仅应用于与 JWT 匹配的用户。
无需身份验证的授权
默认情况下,每次授权检查都隐式要求进行身份验证,但这可以根据每条规则进行禁用。例如,当一个节点具有一个属性来标记该节点是否应为公共节点时,就可能出现这种情况。
例如,在某些 Post
节点是私有的且属于特定 User
,而其他 Post
节点是公共的且可由任何用户读取的情况下,以下是设置方法
type User @node {
id: ID!
}
type Post @node @authorization(filter: [
{
requireAuthentication: false,
operations: [READ],
where: { node: { public: { eq: true } } }
}
]) {
title: String!
content: String!
public: Boolean!
authors: [User!]! @relationship(type: "AUTHORED", direction: IN)
}
规则排序
在每个规则集(filter
和 validate
)中,规则使用 OR
连接。这两个规则集则使用 AND
连接。
例如,如果 JWT 角色声明包含 admin
或节点上的 locked
属性为 false
,则以下内容将允许更新 User
节点
type User @node @authorization(validate: [
{ operations: [UPDATE], where: { jwt: { roles: { includes: "admin" } } } }
{ operations: [UPDATE], where: { node: { locked: false } } }
]) {
id: ID!
locked: Boolean!
}
如果您想将用户必须是管理员的规则与 locked
属性必须为 false
的规则结合起来以更新 User
节点,请将它们都通过 AND
在单个规则中添加到 where
字段
type User @node @authorization(validate: [
{ operations: [UPDATE], where: { AND: [{ jwt: { roles: { includes: "admin" } } }, { node: { locked: false } }] } }
]) {
id: ID!
locked: Boolean!
}