5. 配置路由器
7m

概述

让我们整理一下关于如何在中实施身份验证的学习内容。在本课中,我们将:

  • 配置 将 HTTP 标头传递到
  • 设置 以接收标头和验证用户
  • 测试一个 ,该查询需要使用 进行身份验证和授权
Diagram of step 2 of the migration plan. Step 2 is creating a router running on the original port that is connected to the registry.

服务检查

在继续之前,让我们确保所有进程仍在运行!

  • 应运行一个终端npm start,启动位于端口 4001上 subgragh 服务器的单体
  • 另一个应该运行 npm run launch,在端口 40104011上启动单体目录中的服务。

✏️ 下载路由器

  1. 打开一个新的终端窗口,并导航到 router目录。

  2. 通过在终端中运行以下命令下载

    router
    curl -sSL https://router.apollo.dev/download/nix/v1.46.0 | sh

    注意:访问官方文档来 探索路由器下载的备用方法

  3. 现在,当我们检查 router目录的内容时,我们会发现我们也有一个新文件,也称为 router

    📦 router
    ┣ 📄 router
    ┣ 📄 router-config.yaml
    ┗ 📄 supergraph-config.yaml
  4. 我们应该做的最后一项更改。我们最初将图表中环境变量存储在 .env文件中的单体目录中,以便我们轻松地回溯它们。我们将继续引用存储在 .env文件中的 ,因为我们与 一起工作,所以让我们 移动该文件从单体目录进入 router目录。

    📦 router
    ┣ 📄 .env
    ┣ 📄 router
    ┣ 📄 router-config.yaml
    ┗ 📄 supergraph-config.yaml

路由器的配置文件

在启动 之前,让我们来了解其配置文件。在 router-config.yaml中,我们会发现已经指定了一个配置选项:

router-config.yaml
include_subgraph_errors:
all: true # Propagate errors from all subgraphs

默认情况下,出于安全原因,从 日志中省略了错误。我们在配置文件中引用的设置 include_subgraph_errors在与 进行通信时共享任何错误详细信息的设置。通过将 all键设置为 true,我们告诉 我们希望了解在我们 全部 中发生的错误。

这对于开发很有用,因为它将帮助我们解决在此过程中出现的所有问题!

✏️ 添加 Authorization 标头

注意:在中实施身份验证还有其他方法,例如在架构中使用授权、使用协处理器或使用 JWT 身份验证插件。在本课程中,我们将专注于中使用标头传播的身份验证。你可以组合策略来处理许多身份验证要求和实践“纵深防御”。有关这些方法的更多信息,请查看此 Apollo 技术说明

让我们为router-config.yaml文件添加另一个配置选项。

我们希望告诉向其发送Authorization标头,并包含每个请求。

router-config.yaml
headers:
all:
request:
- propagate:
named: "Authorization"

让我们分解这些新行做什么。

  • headers键是我们设置所有 HTTP 标头规则的位置。

  • all表示嵌套在下面的规则将应用于所有上。我们可以使用subgraphs键指定哪些,但我们知道对于 Airlock,我们需要将它传递给所有子图。

  • request指定包含的头应该应用于 接收的请求。

  • 最后,我们希望将 Authorization 头传递给所有 ,所以我们将使用 propagate 键,然后用 named: 'Authorization' 指出头的名称。

注意:你可以 参阅 Apollo 文档,进一步了解传递哪些 HTTP 头的其他方式。

我们的 已全部设置好,将这些身份验证头传递给其 ,让我们确保子图准备好接收这些头并将其传递给自身的

为身份验证设置子图

好消息是,整体 已经为身份验证设置好了!

还记得整体 还是一个独立的 的时候吗?嗯,它已经采用 Authorization 头,使用账户服务检索用户令牌并验证它!

我们看看代码中的这个逻辑。

打开 monolith/index.js 文件,我们的整体 。向下滚动到启动服务器的位置,我们可以找到 context 属性并查看该逻辑:

monolith/index.js
context: async ({ req }) => {
const token = req.headers.authorization || "";
const userId = token.split(" ")[1]; // get the user name after 'Bearer '
let userInfo = {};
if (userId) {
const { data } = await axios.get(`https://127.0.0.1:4011/login/${userId}`).catch((error) => {
throw AuthenticationError();
});
userInfo = { userId: data.id, userRole: data.role };
}
const { cache } = server;
return {
...userInfo,
dataSources: {
bookingsDb: new BookingsDataSource(),
reviewsDb: new ReviewsDataSource(),
listingsAPI: new ListingsAPI({cache}),
accountsAPI: new AccountsAPI({cache}),
paymentsAPI: new PaymentsAPI({cache}),
},
};
},

有了这个逻辑,我们不必在 index.js 文件中做任何额外的工作!

使用配置运行路由器

让我们运行

  1. 在新终端中,导航到 路由器 目录。

  2. 要启动 ,我们将键入我们的 APOLLO_KEYAPOLLO_GRAPH_REF。(记住,您可以在 .env 文件中找到这些 !)然后,使用 ./router 启动 ,最后添加 --config 标志以及 router-config.yaml 文件的路径。

    router
    APOLLO_KEY=<APOLLO_KEY> APOLLO_GRAPH_REF=<APOLLO_GRAPH_REF> ./router --config router-config.yaml

    我们应该会在终端中看到输出消息,其中我们的 127.0.0.1:4000 处运行。

记住端口 4000 是最初的单体 运行的位置?现在我们已经成功地用 替换了它!客户端无需采取任何额外操作来更改其端点,它们可以像往常一样继续

👩🏽‍🔬 测试 认证 标头

让我们试一试!我们可以回到 Studio 中的 Explorer 来测试 以进行

我们将尝试 ,该 需要认证且授权的用户:检索房东的房源。此 需要您以房东身份登录。

通过 Explorer,我们来构建一个来检索宿主的房源信息。对于每个房源信息,我们都会请求其标题每晚价格描述缩略图床位数以及房源类型

query GetHostListings {
hostListings {
title
costPerNight
description
photoThumbnail
numOfBeds
locationType
}
}

让我们运行此,等等!出现AuthenticationError,提示未登录用户😱

慌乱一阵后,让我们重新思考一下遗漏的部分。

我们刚刚设置了授权头作为服务器端处理,但实际上并没有发送与请求关联的头。因此,我们的服务器试图对发送请求的用户进行身份验证,但找不到该用户,接着返回了相应的错误。

让我们继续添加这些头。在 Explorer 的底部面板中,打开Headers选项卡。

点击新建头并将头键设置为Authorization。将值设置为Bearer user-1。我们知道user-1是宿主!

http://studio.apollographql.com
Screenshot of Studio showing where the Headers panel is on the bottom of the screen and where to add the authorization headers
Authorization: Bearer user-1

让我们再次运行此!我们获得了所请求的列表,其中包含我们所需的所有

我们收到ForbiddenError,显示只有宿主有权访问房源信息 - 我们作为访客登录,非常棒,我们的服务器正在按预期运行!

Diagram of step 2 of the migration plan, checked off and completed. Step 2 is creating a router running on the original port that is connected to the registry.

练习

config.yaml
headers:
all:
request:
- propagate:
named: "airlock-cookie"
在上面的 config.yaml 文件中,propagate 键会通知路由器执行什么操作?

要点

  • 要从向下传递授权标头到其,我们需要设置路由器的配置文件。
    • 在配置文件中,我们可以设置headers属性,并使用propagate属性。
  • 一个可以通过其ApolloServer构造函数的context属性从访问授权(和其他请求)标头。
  • 我们可以使用 Apollo Explorer 的标头面板为我们的请求设置授权标头。

下一步

我们在迁移计划中又完成了一项任务,我们准备继续进一步分离这个

上一个

分享你关于本课程的问题和评论

你的反馈有助于我们改进!如果你遇到障碍或困惑,请告诉我们,我们会帮你的。所有评论都是公开的,并且必须遵守 Apollo 行为准则。请注意,已解决或已处理的评论可能会被移除。

你需要一个 GitHub 账户才能在下面发帖。没有一个? 转而在我们的 Odyssey 论坛发帖。