NestJS自定义Guard中Reflector注入失败问题求助
问题描述
在Nest应用中尝试使用Reflector的getAllAndOverride方法读取路由装饰器时遇到以下问题:
- 自定义Guard继承Passport的AuthGuard时,Reflector对象存在但并非Reflector实例
- 仅实现CanActivate接口时,Reflector为undefined
两种情况调用getAllAndOverride均报错
创建了基础测试项目test-guard,仅做了以下修改:
- 新增自定义装饰器
public.decorator.ts:
import { SetMetadata } from '@nestjs/common'; export const PUBLIC_KEY = 'isPublic'; export const Public = () => SetMetadata(PUBLIC_KEY, true);
- 新增自定义Guard
test-guard.ts:
import { Reflector } from '@nestjs/core'; import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Observable } from 'rxjs'; import { PUBLIC_KEY } from './public.decorator'; Injectable() export class TestGuard implements CanActivate { constructor(private readonly reflector: Reflector) {} canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> { console.log(typeof(this.reflector)); console.log(this.reflector instanceof Reflector); const isPublic = this.reflector.getAllAndOverride(PUBLIC_KEY, [ context.getHandler(), context.getClass(), ]); if (isPublic) return true; return false; } }
- 在AppModule中通过Provider注册全局守卫:
{ provide: APP_GUARD, useClass: TestGuard, },
测试时出现报错,TestGuard中的this.reflector为undefined,报错信息如下:
[12:00:55] File change detected. Starting incremental compilation... [12:00:55] Found 0 errors. Watching for file changes. [Nest] 7844 - 14-01-2024 12:00:55 LOG [NestFactory] Starting Nest application... [Nest] 7844 - 14-01-2024 12:00:55 LOG [InstanceLoader] AppModule dependencies initialized +8ms [Nest] 7844 - 14-01-2024 12:00:55 LOG [RoutesResolver] AppController {/}: +12ms [Nest] 7844 - 14-01-2024 12:00:55 LOG [RouterExplorer] Mapped {/, GET} route +2ms [Nest] 7844 - 14-01-2024 12:00:55 LOG [NestApplication] Nest application successfully started +2ms undefined false [Nest] 7844 - 14-01-2024 12:00:57 ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'getAllAndOverride') TypeError: Cannot read properties of undefined (reading 'getAllAndOverride') at TestGuard.canActivate (C:\wamp64\www\test-guard\src\test-guard.ts:14:41) at GuardsConsumer.tryActivate (C:\wamp64\www\test-guard\node_modules\@nestjs\core\guards\guards-consumer.js:15:34) at canActivateFn (C:\wamp64\www\test-guard\node_modules\@nestjs\core\router\router-execution-context.js:134:59) at C:\wamp64\www\test-guard\node_modules\@nestjs\core\router\router-execution-context.js:42:37 at C:\wamp64\www\test-guard\node_modules\@nestjs\core\router\router-proxy.js:9:23 at Layer.handle [as handle_request] (C:\wamp64\www\test-guard\node_modules\express\lib\router\layer.js:95:5) at next (C:\wamp64\www\test-guard\node_modules\express\lib\router\route.js:144:13) at Route.dispatch (C:\wamp64\www\test-guard\node_modules\express\lib\router\route.js:114:3) at Layer.handle [as handle_request] (C:\wamp64\www\test-guard\node_modules\express\lib\router\layer.js:95:5) at C:\wamp64\www\test-guard\node_modules\express\lib\router\index.js:284:15
改用main.ts手动实例化守卫时可正常工作:
app.useGlobalGuards(new TestGuard(new Reflector()),);
问题原因与解决方案
核心问题
TestGuard类上的Injectable()调用缺少**@**装饰器符号,导致Nest无法识别该类为可注入的依赖类,因此不会自动注入Reflector实例。
修复步骤
- 修正
TestGuard的装饰器,添加@符号:
import { Reflector } from '@nestjs/core'; import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Observable } from 'rxjs'; import { PUBLIC_KEY } from './public.decorator'; // 添加@符号 @Injectable() export class TestGuard implements CanActivate { constructor(private readonly reflector: Reflector) {} canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> { console.log(typeof(this.reflector)); console.log(this.reflector instanceof Reflector); const isPublic = this.reflector.getAllAndOverride(PUBLIC_KEY, [ context.getHandler(), context.getClass(), ]); if (isPublic) return true; return false; } }
- 保留AppModule中注册全局守卫的配置,无需手动实例化:
{ provide: APP_GUARD, useClass: TestGuard, },
验证效果
修复后,Nest会自动为TestGuard注入Reflector实例,getAllAndOverride方法可正常调用,全局守卫功能正常工作。后续注入其他服务时,依赖注入机制也能正常生效。
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

