概览
要继续我们的迁移计划,我们需设置路由器以在原始服务器端口(端口 4000
)上运行。在我们对此进行编码之前,我们先了解下我们如何确保 路由器和整体 子图能够正确处理身份验证和授权。在本课中,我们将:
- 回顾 Auth 如何在 Airlock 的整体架构中运作
- 了解如何将授权标头从 路由器传播到其 子图的
Airlock 中的 Auth 如何运作
Airlock 有两种类型的用户:房东和房客。每位用户都可以执行不同种类的操作。
在以房东身份登录时,您可以:
- 创建房源
- 管理房源预订
- 撰写房客评论
在以房客身份登录时,您可以:
- 预订住宿地点
- 撰写位置和房东评论
- 管理您的空间积分
目前,房客用户无法创建房源,而房东用户无法预订住宿地点。
通过这些业务规则,我们的 Airlock GraphQLAPI 需要控制哪些用户能够看到和交互图形中的特定字段。这就是身份验证和授权发挥作用的地方。
- 身份验证就是确定给定用户是否已登录,随后确定他是谁。(用户是他们声称的自己。)
- 授权就是确定给定用户有权限做什么或看到什么。(允许用户执行他们试图执行的操作。)
注意:这是您第一次使用身份验证?请查看身份验证和授权旁支任务以详细了解如何在单个GraphQL 服务器中验证用户登录和权限。
在 Airlock 中,我们使用 HTTP 标头,特别是带有 Bearer 令牌的Authorization
标头来提供我们的用户证书。标头类似于这样:
Authorization: Bearer user-1
当 GraphQL 服务器 收到传入客户端后操作,它从请求头中检索令牌并尝试使用帐户服务对用户进行身份验证。身份验证成功后,帐户服务将返回包含userId
和userRole
的”对象,然后 GraphQL 服务器 会将对象添加到contextValue
对象中,对每个 解析器 都可用。
Airlock 使用字段级授权。这意味着每个解析器都会检查已登录用户是否有权访问图形的该部分。他们使用userId
和userRole
从contextValue
对象中获取属性。
超级图中的身份验证
在最初的单一架构中,GraphQL 服务器从客户端接收授权头,做一些逻辑来提取所需的用户信息,然后通过contextValue
对象将其信息传递给其解析器。
在超图架构中,故事仍然类似。路由器将从客户端接收授权标头,然后将此信息传递给其子图。每个子图将执行相同的逻辑,以提取用户信息并将其传递给其解析程序。
注意:在超图中实现身份验证还有其他方法,例如在架构中使用授权指令,使用协处理器或使用 JWT 身份验证插件。在此课程中,我们将重点介绍子图中使用标题传播进行身份验证。您可以结合这些策略来处理多个身份验证要求并实践“纵深防御”。有关这些方法的更多信息,查看此 Apollo 技术笔记。
路由器如何将此信息传递给其子图?子图需要做什么才能将此信息传递给其 解析程序?让我们深入了解这些问题,并在“超图中的身份验证”这个故事中回答它们!
对用户进行身份验证
故事的开头与我们的GraphQL 查询之旅相同:即客户端向服务器发出请求。此特定请求包括一个Authorization
标头,其中包含已登录用户的凭证。
在收到该请求后,路由器开始创建查询计划,使用超级图模式作为参考,以确定要为特定字段查询哪个子图。
下一步,路由器执行查询计划。从顶部开始,向子图发送请求。该请求包含客户端发送的Authorization
标头!
但是路由器如何知道要传递该标头?这在配置中都有说明!
向子图发送 HTTP 标头
我们启动路由器时,可以选择使用--config
标志传入配置文件。这样,我们可以通过多种方法自定义路由器,例如配置 CORS(我们在最终第 1 部分看到了它),自省和 HTTP 标头。
使用配置文件时,我们会告诉路由器将Authorization
标头在其子图的每个请求中发送给子图。我们将在下一课中了解此配置的实际作用。
发送到子图中
当 子图 接收到来自 路由器 的请求时,它从请求中访问 Authorization
标头并尝试对用户进行身份验证。
如果尝试不成功,则 子图 停止并发送 AuthenticationError
返回到 路由器,后者会将它直接发送回客户端。
如果身份验证成功,则 子图 将包含用户信息的对象放在一起,并使其在上下文中可用。此用户信息对象可以以最有利于子图的 解析器 的方式构建,并通过 contextValue
对象传递。
该 子图 解析 操作 的方式与任何其他 GraphQL 服务器 相同:它们使用自己的 解析器 和 数据源 来检索和填充请求的数据。它们可以在 contextValue
对象中使用用户信息,以检查对特定业务规则的保护以及谁有权访问它!
返回路由器
该 子图向 路由器发送回请求的数据,而路由器继续执行其 查询计划,最终将所有这些响应合并到单个 JSON 对象中。
最后, 路由器将最终 JSON 对象发送回客户端。这就是我们的 操作之旅的终点!
练习
config
文件的一部分?要点
- 在 Airlock 中,客户端将其请求发送到 路由器,同时添加了一个名为
Authorization
的 HTTP 标头,其中包含当前用户的身份验证令牌。 - 路由器可以用一个配置文件进行自定义,以将 HTTP 标头传递给其 子图。
- 路由器将用户的身份验证令牌传递给 子图,该 子图检查令牌是否有效用于登录。
- 如果登录不成功,子图将抛出
AuthenticationError
并将其发回路由器。 - 如果登录成功,子图将当前用户信息添加到其
contextValue
对象中,其解析器可通过此对象访问,以实现字段级授权。
- 如果登录不成功,子图将抛出
下一步
我们已经了解如何在超图中处理身份验证,因此让我们整合所有内容并在代码中实现这一点!
分享您对本课的疑问和评论
您的反馈有助于我们提升!如果您遇到了困难或困惑,请告知我们,我们会为您提供帮助。所有评论都是公开的,且必须遵守 Apollo 行为准则。请注意,已解决或已处理的评论可能会被删除。
您需要一个 GitHub 帐户才能在下面发帖。没有帐户? 转而发帖至我们的 Odyssey 论坛。