概述
在上节中,我们了解到 认证是确定给定用户是否已登录,然后确定某人是谁的过程。换句话说,认证是检查用户所言是否属实。
Airlock 使用简化的登录流程:用户可以以主机帐户或访客帐户登录。你可以在以下位置测试登录流程https://127.0.0.1:3000/login
(或 已部署的 Airlock 演示应用)。
在本课程中,我们将
- 学习如何使用 Apollo Server
context
对象使用 HTTP 标头认证用户。
🕵️♂️ 认证
有许多方法可以提供认证凭据,例如 HTTP 标头、会话 cookie 或 JSON web 令牌。
Airlock 使用 HTTP 标头。让我们仔细看看它是如何工作的。
在客户端
记住 GraphQL 操作 以 HTTP 请求的形式从客户端发送到服务器。在 Airlock 中,每个操作都包含一个 HTTP Authorization
标头,其中带有 Bearer 令牌,以提供身份验证凭据。该标头类似于以下内容:
Authorization: Bearer user-1
注意:如果您好奇,您可以在 client/src/index.js
(authLink
变量 设置的地方)中看到添加此标头的客户端代码。
设置客户端身份验证不在本任务的范围内,因此我们不会详细介绍这一点。有关更多信息,您可以查看 Apollo Client 身份验证文档。
在上面的示例中,user-1
令牌指示哪个用户正在提出请求。我们可以看到,令牌只是“user-1”,这是用户的确切 ID。在生产环境中,此令牌通常采用临时编码字符串的形式,该字符串由您的用户管理系统(如 Auth0 或 Okta)生成。但出于本课程的目的,我们坚持使用普通用户 ID,以便在测试时简化操作。
在服务器端
当 GraphQL 服务器 接收到传入的客户端 操作 时,它会从请求标头中检索令牌,并尝试对用户进行身份验证。让我们来看看 Airlock 如何细分此过程中的步骤:
- 该 GraphQL 服务器 从客户端请求的
Authorization
标头中检索 Bearer 令牌。 - 如果存在 Bearer 令牌,服务器会将其传递给
accounts
服务,该服务尝试登录相应用户。 - 如果用户登录成功,
accounts
服务将会返回用户个人资料数据对象。然后,GraphQL 服务器将用户的 ID 和角色添加到context
对象中以供每个解析器使用。
从那里开始,每个解析器都能出于授权目的使用这些用户属性,以确定用户拥有哪些数据访问权限。(不过我们会在下一课中介绍!)
相关代码位于server/index.js
文件中,ApolloServer
初始化的context
属性中:
// ...context: async ({ req }) => {// 1) Retrieve the Bearer token from the request's Authorization header// (Note the lowercase "a" in authorization,// because all headers are transformed to lowercase)const token = req.headers.authorization || '';// Get the user token after "Bearer "const userId = token.split(' ')[1]; // e.g. "user-1"// Initialize the userInfo object where the user's id and role will be stored// with a successful authenticationlet userInfo = {};if (userId) {// 2) Authenticate the user using the accounts API endpointconst { data } = await axios.get(`https://127.0.0.1:4011/login/${userId}`).catch((error) => {throw AuthenticationError();});// 3) After a successful login, store the user's id and role// in the userInfo object,// which will be passed to `context` below for the resolvers to useuserInfo = { userId: data.id, userRole: data.role };}// for RESTDataSource classesconst { cache } = server;// Below is the `context` object resolvers will have access toreturn {...userInfo,dataSources: {bookingsDb: new BookingsDataSource(),reviewsDb: new ReviewsDataSource(),listingsAPI: new ListingsAPI({cache}),accountsAPI: new AccountsAPI({cache}),paymentsAPI: new PaymentsAPI({cache}),},};},// ...
练习
要点
- 一种用户身份验证的方式是通过传递 HTTP
Authorization
请求标头,其中包含GraphQL 它发送到服务器的操作。 - 身份验证逻辑可以在
context
属性中编写ApolloServer
构造函数,以便用户信息对每个解析器可用。
下一步
既然我们已经了解了 Airlock 如何处理认证,下一步是授权。在下一课中,我们将了解 Airlock 如何使用 context
对象中的用户信息来确定用户是否有权执行某些 操作.