【问题标题】:NestJS: UseGuards Doesn't Use Dependency Injection - Can't Override GuardNestJS:UseGuards 不使用依赖注入 - 无法覆盖 Guard
【发布时间】:2021-12-09 02:58:39
【问题描述】:

当前行为

文档声明here

...我们传递了 RolesGuard 类型(而不是实例),将实例化的责任留给框架并启用依赖注入。

所以我希望通过模块的providers 用另一个守卫“覆盖”守卫。 这没有按预期工作。

有趣的是, 不过,通过控制器的构造函数注入相同的服务确实会产生正确的服务。

输入代码

简单:https://github.com/dima-gusyatiner/nestjs-guards-override/tree/only-app-module

与另一个模块,使用exportshttps://github.com/dima-gusyatiner/nestjs-guards-override/tree/master

控制器:

@Controller()
@UseGuards(AuthGuard)

模块:

@Module({
  controllers: [AppController],
  providers: [
    {
      provide: AuthGuard,
      useClass: AuthOverrideGuard,
    }
  ],
})

预期行为

我希望AuthGuard 甚至永远不会被构建。 相反,两个类都被构造,AuthGuard 被用作守卫。

环境

- Nest version: 8.0.6
- Node version: 16.8.0
- Platform: Linux

错误报告

我还为此开了一张票: https://github.com/nestjs/nest/issues/8011

问题

我在这里做错了什么,还是这是一个错误? 任何人都可以提出解决方法?

【问题讨论】:

  • 我不得不说这是一个非常有趣的案例。无论如何,你能解释一下你为什么需要它吗?如果你需要它,看起来你做错了什么(即使它是一个错误)

标签: dependency-injection nestjs inversion-of-control


【解决方案1】:

我也不确定我是否理解得很好,但从我所见:

  • 使用 UseGuards,传入的类不会被解析为提供者。仅当您将守卫声明为依赖项时。就像在 AppController 中一样,它是否在提供程序范围内查找。
  • 确定守卫的依赖关系在调用模块的范围内被解析为提供者,但它本身不是。只是使用依赖注入进行常规实例化。
  • 我认为这就是为什么仍然创建两个保护,只是 AuthOverrideGuard 被注册为提供者。

这就是你得到以下输出的原因:

[Nest] 77074  - 05/09/2021, 05:01:39     LOG [NestFactory] Starting Nest application...
Construct AuthOverrideGuard
Construct AuthGuard
AuthGuard
AppController AuthOverrideGuard {}
  • 这就是为什么 this.guard 在提供者范围内被正确解析为 AuthOverrideGuard 的原因

【讨论】:

    【解决方案2】:

    总而言之,据我了解,文档不准确

    文档声明here

    ...我们传递了 RolesGuard 类型(而不是实例),将实例化的责任留给框架并启用依赖注入

    这是不准确的,因为RolesGuard 不会被正确的依赖注入实例化。相反,它将使用仅使用这个确切的类进行实例化。

    为了实现正确的依赖注入,应该使用另一个类,通过守卫的构造函数注入。例如:

    import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
    import { Observable } from 'rxjs';
    
    import { AuthService } from '../services';
    
    @Injectable()
    export class AuthGuard implements CanActivate {
        constructor(
            private readonly auth: AuthService,
        ) {}
    
        canActivate(context: ExecutionContext) {
            return this.auth.canActivate(context);
        }
    }
    

    您永远不能提供另一个AuthGuard,它不起作用。但是你可以提供另一个AuthService,这个守卫使用。

    @Module({
      controllers: [AppController],
      providers: [
        {
          provide: AuthService,
          useClass: AuthServiceOverride,
        }
      ],
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      • 1970-01-01
      • 2021-03-25
      • 2015-07-16
      • 1970-01-01
      • 1970-01-01
      • 2017-12-11
      相关资源
      最近更新 更多