Аутентификация и роли с охранниками / декораторами: как передать объект пользователя? - PullRequest
0 голосов
/ 17 февраля 2020

С помощью Guards / Decorators я сначала пытаюсь проверить JWT, а затем роли, которые имеет пользователь.

Я прочитал документацию, касающуюся Аутентификации, Guards and Decorators и понимаю принципы, лежащие в их основе.

Однако я не могу как-то сделать аутентифицированного пользователя из 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
    };
  }
}

role.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;
    });
  }
}

role.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);
}

1 Ответ

1 голос
/ 17 февраля 2020

Ваш декоратор и охранники выглядят хорошо, но из фрагмента вашего файла users.controller.ts неясно, действительно ли защита ролей применена для маршрута GET /.

У меня, однако, есть приложение Nest JS с очень похожей настройкой на основе документации по защите . Следующий код в 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 не смог бы получить пользователя запроса.

Кроме того, вы могли бы взглянуть на аналогичный вопрос с некоторого времени go, который содержит некоторые подробности о порядке охраны в разных сферах.

...