简体   繁体   English

RoleGuard 在 Nest JS 中是如何工作的? 与智威汤逊

[英]How does RoleGuard works in Nest JS? with JWT

The feature I am working on is that the system should determine a correct type of user and allow appropriate permissions after successful login and what I had in mind is to use RoleGuard feature of nest JS.我正在研究的功能是系统应该确定正确的用户类型并在成功登录后允许适当的权限,我想到的是使用 nest JS 的 RoleGuard 功能。

But I can't seem to figure out how this RoleGuard really works.And can't seem to make it work.但我似乎无法弄清楚这个 RoleGuard 到底是如何工作的。而且似乎无法让它工作。

I wanted to allow user with specific rules to access some endpoints , like only user with admin role is allowed to get all list of users.我想允许具有特定规则的用户访问某些端点,例如仅允许具有 admin 角色的用户获取所有用户列表。

What seem to be the issue ?似乎是什么问题? Anyone has an idea ?有人有想法吗? I have provided snippets below.我在下面提供了片段。 And upon requesting should I'll just be adding role in the request body ?在请求时,我是否应该只在请求正文中添加角色? or it would be good if Ill get the current logged user and determine the role ?或者如果我获取当前登录的用户并确定角色会很好? Thank you.谢谢你。

Here is my user data which has the role:这是我的用户数据,它具有以下作用:

"id": 11, {
    "role": "admin",
    "username": "myadmin@test.com",
    "created": "2020-03-18T02:30:04.000Z",
    "updated": "2020-03-18T03:02:12.000Z"
}

SampleCode示例代码

 import { JwtAuthGuard } from '../../auth/jwt-auth.guard';
    import { RolesGuard } from '../../common/guards/roles.guard';
    import { Roles } from '../common/decorators/roles.decorator';

    @Controller('user')
    @UseGuards(JwtAuthGuard, RolesGuard)
    export class UserController {
      constructor(private readonly usersService: UsersService) {}

      @Get()
      @Roles('admin')
      findAll(): Promise<UserEntity[]> {
        return this.usersService.findAll();
      }

RoleGuard角色卫士

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

      canActivate(context: ExecutionContext): boolean {
        const roles = this.reflector.get<string[]>('roles', context.getHandler());
        console.log('roles:', roles);
        if (!roles) {
          return true;
        }
        const request = context.switchToHttp().getRequest();
        const user = request.user;
        const hasRole = () => user.roles.some(role => roles.indexOf(role) > -1);
        console.log('hasRole', hasRole);

        return user && user.roles && hasRole();
      }
    }

To this code works you need to add User obj into request context using an AuthGuard.对于此代码,您需要使用 AuthGuard 将 User obj 添加到请求上下文中。

First off you don`t need a JwtAuthGuard if you not implement another things the Standard AuthGuard do, Adding JwtAuthGuard into UseGuards decorator mades a overwrite of default AuthGuard and if you not adding the user obj into request obj inside of JwtAuthGuard code, the RolesGuard not will work correctly.首先,如果您没有实现标准 AuthGuard 所做的其他事情,则不需要 JwtAuthGuard,将 JwtAuthGuard 添加到 UseGuards 装饰器会覆盖默认的 AuthGuard,如果您没有将用户 obj 添加到 JwtAuthGuard 代码中的请求 obj 中,则 RolesGuard 不会将正常工作。

Standard Approach标准方法

If you see the source code into the line 48 the attaches the user obj into request obj.如果您在第 48 行看到源代码,则将用户 obj 附加到请求 obj 中。 After seeing this it`s simply.. just add into @UseGuards decorator the AuthGuard('jwt'),RolesGuards like that看到这个之后它很简单..只需将 AuthGuard('jwt'),RolesGuards 添加到@UseGuards 装饰器中

import { AuthGuard } from '@nestjs/passport';
import { RolesGuard } from '../../common/guards/roles.guard';
import { Roles } from '../common/decorators/roles.decorator';

@Controller('user')
@UseGuards(AuthGuard('jwt'), RolesGuard)
export class UserController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  @Roles('admin')
  findAll(): Promise<UserEntity[]> {
    return this.usersService.findAll();
  }

Doing that the Standard Approach to RolesGuards wil runs correctly... Now if you doing a different things and need a custom AuthGuard.. You need to add the User Obj returned of the validate function of JwtStrategy Class.这样做RolesGuards的标准方法将正确运行......现在如果你做不同的事情并且需要一个自定义的AuthGuard......你需要添加JwtStrategy类的validate函数返回的用户对象。 Like that:像那样:

import { Injectable, ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
    handleRequest(err: any, user: any, info: any, context: ExecutionContext) {
        const request = context.switchToHttp().getRequest();
        request.user = user;
        return user;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM