8

我的任务是将我们的 NestJS 身份验证模块隔离到一个单独的共享库中,以便在多个 NestJS 项目之间重用它。每个项目都存在于每个自己的存储库中,共享库作为 npm 包导入。我正在使用 NestJS 的护照模块进行身份验证(使用 jwt 令牌),并且基本上只是遵循了有关如何实现它的官方文档。

我遵循了其他 NestJS 社区包的模式,到目前为止,我已经移动了大部分身份验证代码并确保它可以编译和运行。

现在,我遇到了一个问题。该应用程序不再识别自定义 jwt 护照策略,在我将它移到图书馆之后,我不知道为什么。我只是得到一个例外:

未知的身份验证策略“jwt”

例子:

这是自定义护照策略和 AuthModule (真实版本更复杂,但这是一个最小可复制示例)。“父”项目和新库项目中的代码完全相同。

import { Injectable, Module } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-custom';

@Injectable()
export class CustomStrategy extends PassportStrategy(Strategy, 'custom') {
  async validate(request: Request): Promise<any> {
    console.log('Custom validation', request);

    return true;
  }
}

@Module({})
export class AuthModule {
  static forRoot() {
    return {
      module: AuthModule,
      providers: [CustomStrategy],
      exports: [CustomStrategy],
    };
  }
}

这就是我在 NestJS 应用程序中注册它的方式:

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { AuthModule } from '@my-org/common';        // Library version
// import { AuthModule } from './auth/AuthModule';  // Local version

@Module({
  imports: [
    AuthModule.forRoot(),
    PassportModule.register({ defaultStrategy: 'custom' })
  ]
})
export class CommonModule {}

export class CustomAuthGuard extends AuthGuard('custom') {}

当从同一个 NestJS 项目中引用 AuthModule 时,一切都会运行,我会收到Custom validation控制台消息。

当从我的 npm 库中导入 AuthModuleUnknown authentication strategy "custom"时,每当我提出请求时,我都会从护照中获得异常。

两边的代码完全一样。模块的用法是完全一样的,不管模块来自哪里。共享库使用与官方 NestJS 包相同的模式设置,例如 @nestjs/common 和 @nestjs/cqrs。库导出的任何其他注册服务都按预期工作(如果需要,我可以包含另一个最小示例来显示这一点)。

我错过了什么?如何使用单独的 npm 包共享我的自定义 NestJS PassportStrategy?

我花了一半的工作日试图解决这个问题,到目前为止,我认为这可能与策略注册的护照实例有关,但我不知道如何测试这个 - 或者,如果这是就算是这样,怎么解决。

4

2 回答 2

1

战略:

import { Strategy } from 'passport-custom';
import { PassportStrategy } from '@nestjs/passport';
import {Injectable, UnauthorizedException} from '@nestjs/common';

@Injectable()
export class CustomStrategy extends PassportStrategy(Strategy, "custom") {
    static key = "custom"

    async validate(req: Request): Promise<User> {
        const valid = true;
        if(!valid) throw new UnauthorizedException();
        return {id: "123", name: "test"};
    }
}

认证模块:

@Module({
  imports: [PassportModule],
  providers: [CustomStrategy]
})
export class AuthModule {}

控制器装饰器:

@UseGuards(AuthGuard(CustomStrategy.key))
于 2021-11-17T10:42:10.773 回答
0

像这样的东西对我有用:

import { Injectable, Module } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-custom';

@Injectable()
export class CustomStrategy extends PassportStrategy(Strategy, 'custom') {
  async validate(request: Request): Promise<any> {
    console.log('Custom validation', request);

    return true;
  }
}

@Module({})
export class AuthModule {
  static forRoot() {
    return {
      module: AuthModule,
      imports: [
        PassportModule.register({ defaultStrategy: 'custom' }),
      ],
      providers: [CustomStrategy],
      exports: [CustomStrategy, PassportModule],
    };
  }
}
于 2021-09-02T08:54:04.307 回答