授权

这是 GraphQL Library 版本 7 的文档。对于长期支持 (LTS) 版本 5,请参阅 GraphQL Library 版本 5 LTS

授权规则规定了生成的 Cypher 查询可以访问哪些特定数据。它们使用谓词来评估由 GraphQL 查询生成的 Cypher 访问的数据,从而允许或禁止在节点及其属性的上下文中执行。

所有授权规则都隐含地要求进行身份验证,因为这些规则通常是根据 JWT 有效负载中的值进行评估的。

在显式身份验证的情况下(使用 @authentication 指令配置),它仅在 Cypher 翻译时进行评估。需要身份验证的未经验证的请求永远不会到达数据库。

@authorization 指令不适用于订阅,它仅适用于查询和变更。相反,如果您打算在 API 中使用订阅并希望保护事件,请使用 @subscriptionsAuthorization 来配置订阅的授权。

筛选规则

筛选规则过滤掉用户无权访问的数据,而不会抛出任何错误。这些规则被转换为筛选谓词,它们根据数据库中匹配的数据进行评估。

此类规则的筛选器的工作方式与查询和聚合的筛选器相同。请参阅 筛选

筛选规则不仅可以保护数据,还可以向未经授权的用户模糊该数据存在的信息。

例如,以下是如何筛选出不属于当前 UserPost 节点

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)
}

如果 operations 参数未提供操作列表,GraphQL Library 会将授权配置视为已提供了完整的操作列表。

验证规则

如果查询执行的数据用户无权访问,则验证规则将抛出错误。这些规则通过包含对 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)
}

如果 operations 参数未提供操作列表,GraphQL Library 会将授权配置视为已提供了完整的操作列表。

时机

可以配置验证仅在操作执行之前或之后执行。这通过使用接受以下值数组的 when 参数来完成

  • 之前

  • 之后

此外,有些操作仅支持在它们之前或之后进行验证,下表对此进行了总结

操作 时机

读取

之前

聚合

之前

创建

之后

更新

BEFOREAFTER

删除

之前

创建关系

BEFOREAFTER

删除关系

BEFOREAFTER

举例来说,假设您希望某人能够更新帖子。如果您想在更新后检查帖子的作者是否仍是当前用户,请执行以下操作

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)
}

规则排序

在每个规则集(filtervalidate)中,规则使用 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!
}
© . All rights reserved.