NestJs - 无法在RolesGuard中获取用户上下文

Kev*_*aus 7 javascript nestjs

我使用NestJS作为客户端API的框架.在框架内,我们正在使用一个非常标准的Passport/JWT auth基础设施,该工作正常.我们的AuthGuard在找到承载令牌时触发,并且在安全的API端点中,我可以通过'@Res()request注入HTTP上下文并访问'request.user'属性,该属性包含我的Jwt令牌的有效负载.

最重要的是,我们尝试以与文档中提供的示例代码非常相似的方式实现"RolesGuard"以及GitHub上的一些示例项目(其中没有一个实际使用此防护,但它们将其作为示例防护包括在内).

我们的问题是我们的AuthGuard会触发并验证Jwt令牌,然后我们的RolesGuard会触发,但它传递的请求对象没有附加到请求的用户元数据.

我们的RolesGuard中的关键代码是:

    const request = context.switchToHttp().getRequest();
    const user = request.user;

    if (!user) {
        return false;
    }
Run Code Online (Sandbox Code Playgroud)

在上面剪断的用户总是假的.有没有人在Nest中编写了一个基于角色/权限的保护,成功访问了当前用户的范围?所有代码都被触发,所有内容都显示正确.

-Kevin

Kev*_*aus 9

最终,这似乎是警卫的排序问题,并且它看起来不容易解决(没有框架允许对排序进行一些控制).

我希望在全球范围内注册RolesGuard,但这会导致它首先注册并首先开火.

@UseGuards(AuthGuard('jwt'), RolesGuard)
@Roles('admin')
Run Code Online (Sandbox Code Playgroud)

如果我在端点级别注册它并将其放在AuthGuard之后然后它会触发第二个并且我获得了我期望在防护本身内的用户上下文.它不完美,但它的工作原理.

-Kevin


小智 9

让您的 RolesGuard 扩展 AuthGuard('StrategyName') ,然后调用 super.canActivate 例如:

@Injectable()
export class RolesGuard extends AuthGuard('jwt') {
    async canActivate(context: ExecutionContext): Promise<boolean> {

        // call AuthGuard in order to ensure user is injected in request
        const baseGuardResult = await super.canActivate(context);
        if(!baseGuardResult){
            // unsuccessful authentication return false
            return false;
        }

        // successfull authentication, user is injected
        const {user} = context.switchToHttp().getRequest();
    }
}
Run Code Online (Sandbox Code Playgroud)

换句话说,您必须先进行身份验证,然后再进行授权


小智 8

在端点级别注册 RoleGuard 并将其放在 AuthGuard 之后,然后它第二次触发,我在防护本身内获得了我期望的用户上下文。不要在模块中注册 RoleGuard,因为它将首先注册并首先触发。

*.module.ts

imports: [],
  providers: [{provide: APP_GUARD, useClass: RolesGuard} ,],  // remove guard
  controllers: [],
  exports: [],
Run Code Online (Sandbox Code Playgroud)