@nestjs - JwtModule.registerAsync 未及时注册,无法解决依赖关系

问题描述 投票:0回答:1

使用

registerAsync
功能和
JwtModule
+
JwtService
时遇到一些问题。我浏览了很多关于此的其他线程,似乎每个人都挂在
ConfigModule
上,但我在这个项目中没有使用
ConfigModule

让我从设置开始:

// secret-key.helper.ts

/*
  Retrieve the JWT secret value from AWS Secrets Manager. This is used to
  sign JWTs. Dont worry about imports, they're there.
*/
async function retrieveJwtSecret(): Promise<string> {
  const secretClient = new SecretsManagerClient({
    region: process.env.AWS_REGION,
  });
  const getSecretCom = new GetSecretValueCommand({
    SecretId: process.env.JWT_SECRET_ARN,
  });
  const jwtSecret = (await secretClient.send(getSecretCom)).SecretString;
  return jwtSecret;
}
// auth.module.ts

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtModule } from '@nestjs/jwt';
import { retrieveJwtSecret } from '../../utils/secret-key.helper';

@Module({
  imports: [
    JwtModule.registerAsync({
      useFactory: async () => ({
        global: true,
        secret: await retrieveJwtSecret(),
        signOptions: { expiresIn: '16h' },
      }),
    }),
  ],
  controllers: [AuthController],
  providers: [AuthService],
})
export class AuthModule {}
// my.guard.ts

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Request } from 'express';
import { logEvent } from '../log-event.helper';
import { JwtService } from '@nestjs/jwt';
import { JwtPayloadDto } from 'src/models/auth/dto/jwt-payload.dto';

@Injectable()
export class MyGuard implements CanActivate {
  constructor(private jwtService: JwtService) {}
  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : undefined;
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const req = context.switchToHttp().getRequest();

    /* JWT Authentication */
    const token = this.extractTokenFromHeader(req);
    if (!token) {
      logEvent('ERROR: No token found.', req.headers);
      return false;
    } else {
      const payload = this.jwtService.decode(token) as JwtPayloadDto;
      logEvent('Token found.', payload);
      return true;
    }
  }
}

第一种方法是我如何从AWS秘密管理器检索我的JWT秘密密钥。第二个代码块是

auth
模块,显示
registerAsync
全局导入和
retrieveJwtSecret()
方法的使用(这就是导致问题的原因)。第三个代码块是我正在使用的守卫。

Nest 遇到正在导入/使用的 Guard 的第一个模块返回“无法解析依赖项”错误。当我从

registerAsync
切换到
register
时,将密钥拉入
main.ts
并手动将其放入
process.env
中,一切运行正常。

确切的错误是:

ERROR [ExceptionHandler] Nest can't resolve dependencies of the MyGuard (?).
Please make sure that the argument JwtService at index [0] is available in the BenefitsModule context.

Potential solutions: ...

通过使用

console.log
,我发现执行从
retrieveJwtSecret
函数开始,并且在运行时,它可以访问必要的 .env 变量。然而,它永远不会完全完成
const jwtSecret = await secretClient.send...
调用,我的猜测是,Nest 在收到秘密并完成设置
JwtModule
之前,会继续加载需要
JwtModule
的模块。

如果可能的话,我想远离我提到的

register
实现。有没有办法强制 Nest 等待
async
依赖项被
await
开启?

谢谢!

typescript express asynchronous jwt nestjs
1个回答
0
投票

global

JwtModule.registerAsync
选项应该与
useFactory
处于同一级别,而不是
useFactory
返回的选项的一部分。所以你的模块应该是:

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtModule } from '@nestjs/jwt';
import { retrieveJwtSecret } from '../../utils/secret-key.helper';

@Module({
  imports: [
    JwtModule.registerAsync({
      global: true,
      useFactory: async () => ({
        secret: await retrieveJwtSecret(),
        signOptions: { expiresIn: '16h' },
      }),
    }),
  ],
  controllers: [AuthController],
  providers: [AuthService],
})
export class AuthModule {}

这将使

JwtModule
实际上全球化。

© www.soinside.com 2019 - 2024. All rights reserved.