首页 > 解决方案 > 是否可以使用范围为一的控制器/方法覆盖全局范围的警卫

问题描述

我正在使用 NestJS 框架编写 webAPI。我无法使用放置在方法或控制器级别的全局范围保护来覆盖。我的所有端点都将使用 JWT 验证保护,但用于登录系统的端点除外。是否可以在根级别创建一个守卫,并且只@UseGuard()在单个方法级别使用装饰器覆盖这个全局守卫?

我尝试在listen函数调用之前使用保护并使用APP_GUARD提供程序,但在这两种情况下我都无法覆盖此行为。

代码示例: https ://codesandbox.io/embed/nest-yymkf

标签: nestjs

解决方案


只是加我的 2 美分。

我没有像 OP 那样定义 2 个守卫(rejectaccept),而是定义了一个自定义装饰器:

import { SetMetadata } from '@nestjs/common'

export const NoAuth = () => SetMetadata('no-auth', true)

拒绝守卫 ( AuthGuard) 用于Reflector访问装饰器的元数据,并根据它决定是否激活。

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'
import { Reflector } from '@nestjs/core'
import { Observable } from 'rxjs'

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {

    const noAuth = this.reflector.get<boolean>('no-auth', context.getHandler())

    if(noAuth) return true

    // else your logic here
  }
}

reject然后我在某个模块中全局绑定警卫:

@Module({
  providers: [{
    provide: APP_GUARD,
    useClass: AuthGuard
  }]
})

并在需要的地方继续使用装饰器:

@NoAuth()
@Get() // anyone can access this
getHello(): string {
  return 'Hello Stranger!'
}

@Get('secret') // protected by the global guard
getSecret(): string {
  return 'ssshhh!' 
}

推荐阅读