NestJS中AuthService注入REQUEST导致JWT认证策略错误
解决NestJS注入REQUEST后JWT策略报错的问题
问题根源
注入REQUEST会把AuthService从默认的单例模式改成请求作用域,而Passport的JWT策略在应用启动阶段就需要依赖单例的AuthService完成初始化。请求作用域的服务只有在请求到来时才会实例化,导致启动阶段Passport找不到已注册的"jwt"策略,从而抛出错误。
可行解决方案
拆分请求上下文逻辑:把需要用到REQUEST的部分单独抽成一个请求作用域的服务,让AuthService保持单例。比如创建
RequestContextService:@Injectable({ scope: Scope.REQUEST }) export class RequestContextService { constructor(@Inject(REQUEST) private readonly request: Request) {} getCurrentRequest() { return this.request; } }之后在AuthService里注入这个服务,仅在需要请求信息时调用
getCurrentRequest()方法,既满足需求又不破坏AuthService的单例特性。给JWT策略也设置请求作用域(不推荐):如果一定要让AuthService是请求作用域,就得把JwtStrategy也改成请求作用域,保证两者生命周期一致:
@Injectable({ scope: Scope.REQUEST }) export class JwtStrategy extends PassportStrategy(Strategy) { constructor(private authService: AuthService) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: '你的密钥', }); } async validate(payload: any) { return this.authService.validateUser(payload); } }这种方式会增加每个请求的实例化开销,非必要不建议使用。
在策略或守卫中直接处理请求:如果只是需要获取请求头、参数这类信息,可以在JwtStrategy里直接注入REQUEST,把请求对象作为参数传给AuthService的方法,不用在AuthService构造器里注入:
@Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor( private authService: AuthService, @Inject(REQUEST) private readonly request: Request ) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: '你的密钥', }); } async validate(payload: any) { return this.authService.validateUser(payload, this.request); } }然后在AuthService里定义对应的方法接收request参数即可。
内容的提问来源于stack exchange,提问作者Edison Biba
相关产品推荐
相关产品推荐

