Jwt 策略后 ExecutionContext 中用户丢失

Win*_*ime 1 jwt nestjs

目前我已经实现了 jwt 防护,它工作得很好,使用 Passport,jwt 正在验证颁发的令牌,我可以通过 @Request 通过 req.user 查看用户,在实现基于角色的身份验证作为已经工作的附加组件后出现问题JWT 的守卫。

我遵循了 Nestjs.com 提供的指导,但没有帮助。 https://docs.nestjs.com/guards

基本角色配置:

角色装饰器.ts

import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
Run Code Online (Sandbox Code Playgroud)

角色.guard.ts

import { Injectable, CanActivate, ExecutionContext } 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 true;
    }
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    console.log(user);
    const hasRole = () => user.roles.some((role) => roles.includes(role));
    return user && user.roles && hasRole();
  }
}

Run Code Online (Sandbox Code Playgroud)

RolesGuardapp.module.ts通过以下方式注入到内容中:

providers: [{
    provide: APP_GUARD,
    useClass: RolesGuard,
  }]
Run Code Online (Sandbox Code Playgroud)

我的控制器标头用于验证:

  @UseGuards(AuthGuard('jwt'))
  @Roles('admin')
  @Get('admin')
  async admin(@Request() req) {
    return this.authService.me(req.user);
  }
Run Code Online (Sandbox Code Playgroud)

它应该检查用户是否提供了不记名令牌并且它是活动的,jwt还将用户分配给请求用户,我可以使用@Request() req然后检索它req.user,但是当涉及到时@Roles('admin'),它会undefined在roles.guard.ts “console.log(user)”部分中返回,所以最后,不允许用户查看给定的资源,看起来像是RoleGuard之前注入的AuthGuard('jwt'),但是请求内部有 Brearer 令牌,因此应该将其转换为用户。

我正在考虑改变我的 jwt 策略并实现 CanActivate 接口并将其写在那里,但这对我来说听起来不是一个好的解决方案,因为我想将它们分开。

Jay*_*iel 5

我可以为您确认 是RoleGuard在 之前被调用的,AuthGuard因为 的作用域RoleGuard是全局范围的应用程序(在您定义的位置),而 的AuthGuard作用范围是本地函数。如果您不介意没有RoleGuard全局作用域,而是针对每个方法进行作用域,即使需要编写更多代码,您也可以将其添加到@UseGuards装饰器中。除此之外,就像你说的,你可以将两个守卫合并为一个,但这可能会变得混乱和笨拙。

  • 谢谢杰伊,我想让它成为应用程序的全局,但是正如你所说,角色将在 JWT 验证之前运行,而不是将它们混合起来,我决定使用 `@UseGuards('jwt',RolesGuard)` 来解决问题(位于至少现在,在我们进行生产之前,我必须想出其他办法),谢谢。 (3认同)