使用筛选条件取消订阅 WebSocket 连接 - Amazon AppSync
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用筛选条件取消订阅 WebSocket 连接

在 Amazon AppSync 中,您可以根据特定的筛选逻辑从连接的客户端强制取消订阅并关闭 WebSocket 连接(使其失效)。这在与授权相关的场景中非常有用,例如,在您从组中删除用户时。

订阅失效是针对变更中定义的负载做出的响应。我们建议您将用于使订阅连接失效的变更视为 API 中的管理操作,并仅限管理员用户、组或后端服务使用这些变更以相应地设置其权限范围。例如,使用架构授权指令,例如 @aws_auth(cognito_groups: ["Administrators"])@aws_iam。有关更多信息,请参阅使用其他授权模式

失效筛选条件使用与增强订阅筛选条件相同的语法和逻辑。请使用以下实用程序定义这些筛选条件:

  • extensions.invalidateSubscriptions() - 在变更的 GraphQL 解析器响应处理程序中定义。

  • extensions.setSubscriptionInvalidationFilter() - 在链接到变更的订阅的 GraphQL 解析器响应处理程序中定义。

有关失效筛选扩展的更多信息,请参阅 JavaScript 解析器概述

使用订阅失效

要了解订阅失效在 Amazon AppSync 中的工作方式,请使用以下 GraphQL 架构:

type User { userId: ID! groupId: ID! } type Group { groupId: ID! name: String! members: [ID!]! } type GroupMessage { userId: ID! groupId: ID! message: String! } type Mutation { createGroupMessage(userId: ID!, groupId : ID!, message: String!): GroupMessage removeUserFromGroup(userId: ID!, groupId : ID!) : User @aws_iam } type Subscription { onGroupMessageCreated(userId: ID!, groupId : ID!): GroupMessage @aws_subscribe(mutations: ["createGroupMessage"]) } type Query { none: String }

removeUserFromGroup 变更解析器代码中定义失效筛选条件:

import { extensions } from '@aws-appsync/utils'; export function request(ctx) { return { payload: null }; } export function response(ctx) { const { userId, groupId } = ctx.args; extensions.invalidateSubscriptions({ subscriptionField: 'onGroupMessageCreated', payload: { userId, groupId }, }); return { userId, groupId }; }

在调用变更时,payload 对象中定义的数据用于取消订阅 subscriptionField 中定义的订阅。还会在 onGroupMessageCreated 订阅的响应映射模板中定义一个失效筛选条件。

如果 extensions.invalidateSubscriptions() 负载包含的 ID 与筛选条件中定义的订阅客户端的 ID 匹配,则取消订阅相应的订阅。此外,还会关闭 WebSocket 连接。定义 onGroupMessageCreated 订阅的订阅解析器代码:

import { util, extensions } from '@aws-appsync/utils'; export function request(ctx) { // simplfy return null for the payload return { payload: null }; } export function response(ctx) { const filter = { groupId: { eq: ctx.args.groupId } }; extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter)); const invalidation = { groupId: { eq: ctx.args.groupId }, userId: { eq: ctx.args.userId } }; extensions.setSubscriptionInvalidationFilter(util.transform.toSubscriptionFilter(invalidation)); return null; }

请注意,订阅响应处理程序可以同时定义订阅筛选条件和失效筛选条件。

例如,假设客户端 A 使用以下订阅请求为具有 ID user-1 的新用户订阅具有 ID group-1 的组:

onGroupMessageCreated(userId : "user-1", groupId: :"group-1"){...}

Amazon AppSync 运行订阅解析器,这会生成前面的 onGroupMessageCreated 响应映射模板中定义的订阅和失效筛选条件。对于客户端 A,订阅筛选条件仅允许将数据发送到 group-1,并为 user-1group-1 定义了失效筛选条件。

现在假设客户端 B 使用以下订阅请求为具有 ID user-2 的用户订阅具有 ID group-2 的组:

onGroupMessageCreated(userId : "user-2", groupId: :"group-2"){...}

Amazon AppSync 运行订阅解析器,这会生成订阅和失效筛选条件。对于客户端 B,订阅筛选条件仅允许将数据发送到 group-2,并为 user-2group-2 定义了失效筛选条件。

接下来,假设使用变更请求创建 ID 为 message-1 的新组消息,如以下示例中所示:

createGroupMessage(id: "message-1", groupId : "group-1", message: "test message"){...}

与定义的筛选条件匹配的订阅客户端通过 WebSockets 自动收到以下数据负载:

{ "data": { "onGroupMessageCreated": { "id": "message-1", "groupId": "group-1", "message": "test message", } } }

客户端 A 收到该消息,因为筛选条件与定义的订阅筛选条件匹配。不过,客户端 B 不会收到该消息,因为该用户不属于 group-1。此外,请求与订阅解析器中定义的订阅筛选条件不匹配。

最后,假设使用以下变更请求从 group-1 中删除了 user-1

removeUserFromGroup(userId: "user-1", groupId : "group-1"){...}

该变更启动 extensions.invalidateSubscriptions() 解析器响应处理程序代码中定义的订阅失效。然后,Amazon AppSync 取消订阅客户端 A 并关闭其 WebSocket 连接。客户端 B 不受影响,因为变更中定义的失效负载与其用户或组不匹配。

在 Amazon AppSync 使连接失效时,客户端收到一条消息,以确认已将它们取消订阅:

{ "message": "Subscription complete." }

在订阅失效筛选条件中使用上下文变量

与增强订阅筛选条件一样,您可以在订阅失效筛选条件扩展中使用 context 变量以访问某些数据。

例如,可以在变更中将电子邮件地址配置为失效负载,然后将其与通过 Amazon Cognito 用户池或 OpenID Connect 授权的订阅用户的电子邮件属性或声明进行匹配。失效筛选条件(在 extensions.setSubscriptionInvalidationFilter() 订阅失效器中定义)检查变更的 extensions.invalidateSubscriptions() 负载设置的电子邮件地址是否与从用户 JWT 令牌的 context.identity.claims.email 中检索的电子邮件地址匹配,从而启动失效。