在 Guard 中访问请求的原始正文?

dre*_*dre 9 nestjs

有没有办法访问请求的原始正文?不是已经解析成json了吗?

@Injectable()
export class WooGuard implements CanActivate {
  secret: string;

  constructor(
    private readonly reflector: Reflector,
    private configService: ConfigService,
    ) {
      this.secret = this.configService.get<string>("woocommerce.webhook.secret");
    }

  async canActivate(
    context: ExecutionContext,
    ): Promise<boolean> {

    const request = context.switchToHttp().getRequest<Request>();
    request.body // this is parsed json

    // I am calculating the sha256 hash of the body with a secret for a webhook.
    // due to how the raw json is vs. the JSON.stringify(request.body), the signature is never the same.
  }
}
Run Code Online (Sandbox Code Playgroud)

And*_*scu 5

main.ts您可以在(初始化后)添加一个中间件app,以防止 NestJS 将正文解析为您需要的特定路由的 JSON。

import { raw } from 'body-parser'

const app = await NestFactory.create(AppModule);

// Will keep the raw body
app.use('/users', raw({type: 'application/json'}));
Run Code Online (Sandbox Code Playgroud)

该路由下的所有请求都/users将具有原始正文。

优点:对于 1-2 个端点、测试等来说快速、简单。
缺点:对于许多路由来说可能会变得很麻烦。可以禁用 body-parser 并创建 2 个功能中间件(一个用于 raw,一个用于 JSON 解析)。


小智 3

Shopify 有类似的方法来验证请求,这段代码对我有用,也许你可以更改它。

首先你需要安装加密:

npm install --save crypto
Run Code Online (Sandbox Code Playgroud)

然后:

import { Injectable, CanActivate, ExecutionContext, HttpStatus } from '@nestjs/common';
const crypto = require('crypto');

@Injectable()
export class ShopifyAuthGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const secretKey = <MY_KEY>;

    const hmac = request.headers["x-shopify-hmac-sha256"];

    const hash = crypto
      .createHmac('sha256', secretKey)
      .update(request.body)
      .digest('base64');

    if (hmac === hash) {
      return true;
    } else {
      throw new ForbiddenException("Not allowed");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

最后在你的控制器上:

@Post()
@UseGuards(ShopifyAuthGuard)
async createNewOrder(@Body() orderDto: OrderDto) {}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!

  • 你好 - 请问你能发布原始主体的完整工作解决方案吗? (2认同)