如何在 NestJS Guard 中检查角色

问题描述 投票:0回答:1

我有一个提供 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个回答
0
投票

首先,在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
,在守卫中您将没有
requiredRoles
,并且
if
将返回 true。

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

© www.soinside.com 2019 - 2024. All rights reserved.