Nest.js 将变量从中间件传递到控制器

Jon*_*vin 5 express typescript nestjs

我找不到将变量从中间件传递到 Nest.js 中的结构的明确方法。我正在验证我内部的 JWT AuthMiddleware,并且我想让控制器可以访问此令牌。
下面只是我的中间件的摘录,以提供代码示例。我想让token我的控制器内部可访问。

import { Request, Response, NextFunction } from 'express';
// other imports

@Injectable()
export class AuthMiddleware implements NestMiddleware {
  async use(req: Request, res: Response, next: NextFunction) {
    const authHeader = req.header('authorization');

    if (!authHeader) {
      throw new HttpException('No auth token', HttpStatus.UNAUTHORIZED);
    }

    const bearerToken: string[] = authHeader.split(' ');
    const token: string = bearerToken[1];

    res.locals.token = token;
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试通过更改变量来访问令牌res.locals,但响应对象在我的控制器中仍然为空。这是我的控制器,我想在其中访问中间件的令牌:

@Controller('did')
export default class DidController {
  constructor(private readonly didService: DidService) {}

  @Get('verify')
  async verifyDid(@Response() res): Promise<string> {
    console.log(res)
    // {}
    return res;
  }
Run Code Online (Sandbox Code Playgroud)

Aka*_*pta 7

import { Request, Response, NextFunction } from 'express';
// other imports

@Injectable()
export class AuthMiddleware implements NestMiddleware {
  async use(req: Request, res: Response, next: NextFunction) {
    const authHeader = req.header('authorization');

    if (!authHeader) {
      throw new HttpException('No auth token', HttpStatus.UNAUTHORIZED);
    }

    const bearerToken: string[] = authHeader.split(' ');
    const token: string = bearerToken[1];

    res.locals.token  = token;

    next();  ====> add this to middleware
  }
}
Run Code Online (Sandbox Code Playgroud)

控制器

import { Controller, Get, Response } from '@nestjs/common';


@Controller()
export class AppController {
  constructor() {}


  @Get('verify')
  async verifyDid(@Response() res): Promise<string> {
    console.log(res.locals);
    return res;
  }
}
Run Code Online (Sandbox Code Playgroud)

应用中间件

export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(AuthMiddleware).forRoutes('*');
  }
}
Run Code Online (Sandbox Code Playgroud)


Abd*_*auf 6

更好的方法是创建一个参数装饰器并使用它在控制器中注入令牌依赖项,而无需修改控制器的代码以不必要地使用Request/Response

认证中间件

import { Request, Response, NextFunction } from 'express';
// other imports

@Injectable()
export class AuthMiddleware implements NestMiddleware {
  async use(req /*: Request */, res: Response, next: NextFunction) {
    const authHeader = req.header('authorization');

    if (!authHeader) {
      throw new HttpException('No auth token', HttpStatus.UNAUTHORIZED);
    }

    const bearerToken: string[] = authHeader.split(' ');
    const token: string = bearerToken[1];

    req.token  = token; // request type is commented out otherwise typescript won't allow setting this

    next();
  }
}
Run Code Online (Sandbox Code Playgroud)

参数装饰器(./token.decorator.ts):

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const TOKEN = createParamDecorator(
  (_data: unknown, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    return request.token; // extract token from request
  },
);

Run Code Online (Sandbox Code Playgroud)

控制器:

import { Controller, Get, Response } from '@nestjs/common';
import { TOKEN } from './token.decorator';

@Controller()
export class AppController {
  constructor() {}


  @Get('verify')
  async verifyDid(@TOKEN() token): Promise<string> {
    console.log(token);
    return 'whateverYouWant';
  }
}
Run Code Online (Sandbox Code Playgroud)