如何检查Nestjs Guard中的角色

发布于 2025-01-22 06:41:23 字数 1308 浏览 2 评论 0原文

我有一个提供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似乎首先运行,然后是策略。但是,如果我想做额外的警卫和检查,请说角色。一个人在哪里做?我需要在护照策略之后的另一个后卫吗?我有两个角色“用户”和“ admin”。

I have an external service providing a JWT token. In Nestjs i first have JwtGuard class:

@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;
  }
}

and then a passport strategy:

@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;
  }
}

It seems that JwtGuard is running first, then the strategy. But if i want to do additional guards and checks, say for roles. Where does one do that? Do i need another guard that runs after the passport strategy? I have two roles "User" and "Admin".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小嗲 2025-01-29 06:41:23

首先,在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中使用Decorator:

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

因此,在API中,如果您没有family,则在警卫中,您将不会有sircessuriperroles, 如果 block 将返回true。

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

First of all, define a global guard (called RolesGuard) in the AppModule as following:

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

Then within RolesGuard we have the following:

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
  }
}

Then create your own decorator and you can decorate your APIs if you need that API to protect your app based on your guard.

import { SetMetadata } from '@nestjs/common';

export const ROLES_KEY = 'FamilyRoles';
export const FamilyRoles = (...roles: FamilyRole[]) =>
  SetMetadata(ROLES_KEY, roles);

Then you can use your decorator in your API like this:

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

So, in your API, if you won't have FamilyRoles, in the guard you won't have requiredRoles, and the if block will return true.

More info: https://docs.nestjs.com/security/authorization

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文