【问题标题】:Authentication & Roles with Guards/Decorators: How to pass user object?Guards/Decorators 的身份验证和角色:如何传递用户对象?
【发布时间】:2020-05-31 21:48:20
【问题描述】:

在 Guards/Decorators 的帮助下,我尝试先检查 JWT,然后再检查用户的角色。

我已阅读有关身份验证、守卫和装饰器的文档并了解它们背​​后的原理。

但是,我不能以某种方式使来自 JWT-Guard 的经过身份验证的用户对 Roles-Guards 可用。

在我发现的每个示例中,正是这对我感兴趣的部分被跳过/省略了...

感谢每一个提示!

这是我最近的尝试:

jwt.strategy.ts

import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { JwtPayload } from './jwt.model';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      passReqToCallback: true,
      ignoreExpiration: false,
      secretOrKey: '0000',
      expiresIn: '3 days'
    });
  }

  async validate(payload: JwtPayload) {
    return {
      id: payload.id,
      email: payload.email,
      username: payload.username
    };
  }
}

roles.guard.ts

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

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

  canActivate(context: ExecutionContext): boolean {
    const roles = this.reflector.get<string[]>('roles', context.getHandler());

    if (!roles) {
      return false;
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user ??? // THIS is what is missing

    return roles.some((role) => {
      return role === user.role;
    });
  }
}

roles.decorator.ts

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

export const Roles = (...roles: string[]) => SetMetadata('roles', roles);

users.controller.ts

@UseGuards(AuthGuard('jwt'))
@Roles('admin', 'member')
@Get('/')
async doSomething(@Req() req): Promise<User> {
  return await this.usersService.doSomething(req.user.id);
}

【问题讨论】:

    标签: nestjs


    【解决方案1】:

    您的装饰器和守卫看起来不错,但是从您的users.controller.ts 文件的sn-p 中不清楚角色守卫是否实际应用于GET / 路由。

    不过,我确实有一个基于guards documentation 的设置非常相似的 NestJS 应用程序。 users.controller.ts 中的以下代码按预期工作:

    @UseGuards(JwtAuthGuard, RolesGuard)
    @Controller('/users')
    export class UserController {
      constructor(private readonly userService: UserService) {}
    
      @Get()
      @Roles(UserRole.ADMIN)
      public async index(): Promise<User[]> {
        return this.userService.findAll();
      }
    
      // ...
    }
    

    注意身份验证和角色保护是如何在同一范围内激活的,并且JwtAuthGuard 添加在之前 RolesGuard。如果我要更改守卫的顺序,那么RolesGuard 将无法检索请求的用户。

    另外,您可能想看看前段时间的a similar question,其中包含有关不同范围内守卫顺序的一些详细信息。

    【讨论】:

    • 非常感谢您的帮助!我忘记了除了@Roles之外你还需要RolesGuard ......真的是一个不必要的错误。现在它可以按需要工作 - 谢谢!此外,链接线程中有关导入 app.module.ts 的提示也很有价值,否则您总是会得到 403。
    猜你喜欢
    • 2018-12-16
    • 1970-01-01
    • 2020-05-30
    • 1970-01-01
    • 2015-01-09
    • 2019-01-27
    • 2016-09-23
    • 1970-01-01
    • 2021-04-20
    相关资源
    最近更新 更多