【问题标题】:How to check for roles in NestJS Guard如何检查 NestJS Guard 中的角色
【发布时间】:2022-12-24 10:48:01
【问题描述】:

我有一个提供 JWT 令牌的外部服务。在 Nestjs 中,我首先拥有 JwtGuard 类:

@Injectable()
export class JwtGuard extends AuthGuard('JWT_STRATEGY') {
  constructor() {
    super();
  }

  getRequest(context: ExecutionContext) {
    console.log('JwtGuard');
    const ctx = GqlExecutionContext.create(context);
    return ctx.getContext().req;
  }
}

然后是护照策略:

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'JWT_STRATEGY') {
  constructor(private configService: ConfigService) {
    super({
      secretOrKeyProvider: passportJwtSecret({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: configService.get<string>('ADFS_KEYS_URL'),
      }),
      ignoreExpiration: false,
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      audience: configService.get<string>('ADFS_AUDIENCE'),
      issuer: configService.get<string>('ADFS_ISSUER'),
      algorithms: ['RS256'],
    });
  }

  validate(payload: unknown): unknown {
    console.log('jwt strategy');
    console.log(payload);
    return payload;
  }
}

好像是先运行JwtGuard,再运行策略。但是如果我想做额外的保护和检查,比如角色。在哪里做?我是否需要另一个警卫来执行护照策略?我有两个角色“用户”和“管理员”。

【问题讨论】:

    标签: nestjs passport.js


    【解决方案1】:

    首先,在 AppModule 中定义一个全局守卫(称为RolesGuard),如下所示:

    providers: [
      AppService,
      {
        provide: APP_GUARD,
        useClass: JwtAuthGuard,
      },
      {
        provide: APP_GUARD,
        useClass: RolesGuard,
      },
    ]
    

    然后在RolesGuard 中,我们有以下内容:

    export enum FamilyRole {
      Admin = 'Admin',
      User = 'User',
    }
    
    ...
    
    export class FamilyRolesGuard implements CanActivate {
    
      async canActivate(context: ExecutionContext): Promise<boolean> {
        const requiredRoles = this.reflector.getAllAndOverride<FamilyRole>(
          ROLES_KEY,
          [context.getHandler(), context.getClass()],
        );
    
        if (!requiredRoles) {
          return true;
        }
    
        const { user } = context.switchToHttp().getRequest();
        // do the rest and return either true or false
      }
    }
    

    然后创建您自己的装饰器,如果您需要该 API 来根据您的警卫保护您的应用程序,您可以装饰您的 API。

    import { SetMetadata } from '@nestjs/common';
    
    export const ROLES_KEY = 'FamilyRoles';
    export const FamilyRoles = (...roles: FamilyRole[]) =>
      SetMetadata(ROLES_KEY, roles);
    

    然后你可以像这样在你的 API 中使用你的装饰器:

    @Post('user')
    @FamilyRoles(FamilyRole.Admin)
    ...
    

    因此,在您的 API 中,如果您没有 FamilyRoles,那么在守卫中您将没有 requiredRolesif将返回 true。

    更多信息:https://docs.nestjs.com/security/authorization

    【讨论】:

      猜你喜欢
      • 2020-02-10
      • 2019-10-19
      • 1970-01-01
      • 2021-12-07
      • 2022-01-16
      • 2016-06-21
      • 2019-11-15
      • 2014-06-26
      • 2021-02-25
      相关资源
      最近更新 更多