如何使用 Express 和 Apollo-Server 获取 HTTP 授权标头

Posted

技术标签:

【中文标题】如何使用 Express 和 Apollo-Server 获取 HTTP 授权标头【英文标题】:How To Get HTTP Authorization header With Express and Apollo-Server 【发布时间】:2020-08-19 10:38:21 【问题描述】:

我无法访问我的 Apollo-Server 上每个 HTTP 请求中的“授权”标头,使用 express 实现。 这是我设置的 express、Apollo-Server、CORS 等。

const corsConfig = 
  credentials: true,
  allowedHeaders: ['Authorization'],
  exposedHeaders: ['Authorization']
;

const app = express()

const server = new ApolloServer(
    schema,
    context: ( req ) => 
      return 
        req
      ;
    
  );

server.applyMiddleware(
  app,
  path,
  cors: corsConfig
);

http.createServer(app).listen(port, () => logger.info(`Service started on port $port`));

在我的解析器中,我引入了上下文,特别是 req 对象(这是一个示例 graphQL 端点解析器):

const exampleQuery = async (parent, input ,  req ) => 
    console.log(req.headers); 
    /*
    The output of this log:
      
        'content-type': 'application/json',
         accept: '*/*',
        'content-length': '59',
        'user-agent': 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)',
        'accept-encoding': 'gzip,deflate',
         connection: 'close',
         host: 'localhost:3301',
        'Access-Control-Allow-Headers': 'Authorization',
        'Access-Control-Expose-Headers': 'Authorization'
    

    */

我已经向这个端点发送了请求,带有一个“授权”标头,其中包含一个令牌作为值。但是,Authorization 标头不在 req.headers 对象中(实际上,它也不在整个 req 对象中)。我确信我对这个端点的 Postman/Insomnia HTTP 请求正在发送 Authorization 标头,但是它似乎没有通过我的 Apollo-Server。 任何人都知道为什么 Authorization 标头没有通过?

解决方案:

问题实际上是我使用的是 Apollo 联合微服务架构,它需要在网关上进行额外配置才能将 Authorization 标头传递到解析器所在的各个微服务。您必须在 ApolloGateway 构造函数中添加 buildService 函数,在其中指定一个 RemoteGraphQLDataSource willSendRequest of context.req.headers.authentication 到底层微服务

【问题讨论】:

在您的前端 javascript 代码中,您如何设置凭据模式?例如,对于 XHR,您需要设置 'xhr.withCredentials = true' developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/…。使用 Fetch API,您需要设置 "credentials: 'include'" developer.mozilla.org/en-US/docs/Web/API/Fetch_API/…. @sideshowbarker 现在我不涉及任何前端代码。我只是向带有 Postman/Insomnia 的“exampleQuery”端点发送一个带有“授权”标头的 graphQL 发布请求。我的目标是在 exampleQuery 内的 req.headers["Authorization"] 中访问该标头。 【参考方案1】:

它按预期工作,例如

server.ts:

import  ApolloServer, gql, makeExecutableSchema  from 'apollo-server-express';
import express from 'express';
import http from 'http';

const corsConfig = 
  credentials: true,
  allowedHeaders: ['Authorization'],
  exposedHeaders: ['Authorization'],
;

const typeDefs = gql`
  type Query 
    hello: String
  
`;
const resolvers = 
  Query: 
    hello: (_, __,  req ) => 
      console.log(req.headers);
      return 'world';
    ,
  ,
;
const schema = makeExecutableSchema( typeDefs, resolvers );

const app = express();
const path = '/graphql';
const port = 3000;
const server = new ApolloServer(
  schema,
  context: ( req ) => 
    return 
      req,
    ;
  ,
);
server.applyMiddleware( app, path, cors: corsConfig );

http.createServer(app).listen(port, () => console.info(`Service started on port $port`));

通过 curl 发送 GraphQL 查询 HTTP 请求:

curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer abc123" --data ' "query": " hello " ' http://localhost:3000/graphql
"data":"hello":"world"

服务器端日志:

Service started on port 3000
 host: 'localhost:3000',
  'user-agent': 'curl/7.54.0',
  accept: '*/*',
  'content-type': 'application/json',
  authorization: 'Bearer abc123',
  'content-length': '24' 

【讨论】:

以上是关于如何使用 Express 和 Apollo-Server 获取 HTTP 授权标头的主要内容,如果未能解决你的问题,请参考以下文章

使用 Node.js 和 Express 发布时如何访问请求正文?

如何使用 Socket.io 和 Express 进行集群

如何使用 Express 和 NGINX 设置路由?

如何使用 nodejs / express 上传和读取文件

express:如何使用 sendFile 将 html 和 css 一起发送?

如何使用 Express 和 PassportJS 正确报告无效登录?