NestJS 将 Authorization 标头传递给 HttpService

Posted

技术标签:

【中文标题】NestJS 将 Authorization 标头传递给 HttpService【英文标题】:NestJS passing Authorization header to HttpService 【发布时间】:2020-09-18 04:36:39 【问题描述】:

我有一个 NestJS 应用程序,它充当前端和多个其他后端之间的代理。

我基本上希望能够将来自控制器中传入的@Req(请求)的特定标头(授权)传递给 HttpService,然后再与其他后端对话。

用户控制器(有权访问请求)-> 用户服务(注入 httpService 以某种方式已经选择了 Authorization 标头)-> 外部后端。

现在我需要从@Headers 中提取令牌,然后将令牌传递给必须将其粘贴到所有 HttpService 调用的服务。

提前致谢!

【问题讨论】:

您找到解决方案了吗?你能和我分享吗?我面临着同样的挑战。谢谢 @hksfho 我在下面发布了解决方案。需要注意的是,您在后台更改 Axios 实例,因此如果您的模块修改标头后控制器层,您将丢失更改。 【参考方案1】:

除了middleware 答案,我还有另一个使用interceptor 的版本:

@Injectable()
export class HttpServiceInterceptor implements NestInterceptor 
  constructor(private httpService: HttpService) 
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> 
  
    // ** if you use normal HTTP module **
    const ctx = context.switchToHttp();
    const token = ctx.getRequest().headers['authorization'];

    // ** if you use GraphQL module **
    const ctx = GqlExecutionContext.create(context);
    const token = ctx.getContext().token;

    if (ctx.token) 
      this.httpService.axiosRef.defaults.headers.common['authorization'] =
        token;
    
    return next.handle().pipe();
  

如果您使用GraphQLModule,请不要忘记将令牌传递给上下文:

GraphQLModule.forRoot(
  debug: true,
  playground: true,
  autoSchemaFile: 'schema.gql',
  context: ( req ) => 
    return  token: req.headers.authorization ;
  ,
),

一旦准备工作准备就绪,让我们使用拦截器

拦截器可以注入到某个控制器中:

@UseInterceptors(HttpServiceInterceptor)
export class CatsController 

或注册一个全局拦截器,如下所示:

@Module(
  providers: [
    
      provide: APP_INTERCEPTOR,
      useClass: HttpServiceInterceptor,
    ,
  ],
)
export class AppModule 

【讨论】:

【参考方案2】:

我不确定这是否会对您有所帮助,但也许如果您从控制器获取标头并将其放入您的服务函数中...

// 控制器:

@Get()
getAll(@Request() req)
    const header = req.headers;
    return this._zoneService.sendToHttp(header);

也许微服务可以更好?

【讨论】:

问题是我不想对每种方法都这样做。我希望我的 HttpService 实例被告知 ONCE(中间件:esque)添加所述标头【参考方案3】:

好的,我通过实际使用我最初认为的中间件设法解决了这个问题。我不是 100% 确定这是 NEST 方式,但拦截 HttpService 的底层 axios 引用就可以了:

@Injectable()
export class BearerMiddleware implements NestMiddleware 
  constructor(private readonly httpService: HttpService) 
  use(req: Request, res: Response, next: Function) 
    this.httpService.axiosRef.interceptors.request.use(request => 
      request.headers = 
        ...request.headers,
        Authorization: req.headers.Authorization || '',
      ;
      return request;
    );
    next();
  

【讨论】:

No.. 每次调用 use() 时都会创建一个新的拦截器。数据不正确。 @hksfho 哪个更好?

以上是关于NestJS 将 Authorization 标头传递给 HttpService的主要内容,如果未能解决你的问题,请参考以下文章

所有控制器的全局标头(nestJs swagger)

自定义 Authorization HTTP 标头

我应该对 API 密钥使用 Authorization 标头吗

Django-rest-auth 使用 cookie 而不是 Authorization 标头

javascript 使用Redux中间件将Authorization标头注入到redux-api-middleware请求中。

在 NestJS 中添加标头 HttpRequest