22

我使用 NestJS 作为客户端 API 的框架。在框架内,我们使用了一个运行良好的非常标准的 Passport/JWT 身份验证基础设施。当找到承载令牌时,我们的 AuthGuard 正在触发,并且在安全的 API 端点中,我可以通过“@Res() 请求”注入 HTTP 上下文并访问包含我的 Jwt 令牌有效负载的“request.user”属性.

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

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

我们 RolesGuard 中的关键代码是:

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

    if (!user) {
        return false;
    }

在上面的截图中,用户总是假的。有没有人在 Nest 中编写了一个基于角色/权限的守卫,成功地访问了当前用户的范围?所有代码都在触发,并且所有内容都显示正确注册。

-凯文

4

4 回答 4

34

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

我希望在全球范围内注册 RolesGuard,但这会导致它首先注册并首先触发。

@UseGuards(AuthGuard('jwt'), RolesGuard)
@Roles('admin')

如果我在端点级别注册它并将其放在 AuthGuard 之后,那么它会第二次触发,我会在防护本身中获得我期望的用户上下文。它并不完美,但它有效。

-凯文

于 2018-06-11T16:02:37.400 回答
3

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

*.module.ts

imports: [],
  providers: [{provide: APP_GUARD, useClass: RolesGuard} ,],  // remove guard
  controllers: [],
  exports: [],
于 2019-07-30T10:58:10.707 回答
1

让您的 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();
    }
}

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

于 2021-09-30T18:43:16.447 回答
1

如果其他人偶然发现了这个问题:将多个警卫放入一个@UseGuards装饰器中是可行的,但是如果您想让它们分开(例如,如果您使用自定义装饰器),您可以通过在调用之前req.user放置第二个警卫来访问它将用户放在请求对象上,如下例所示:@UseGuards

@RestrictTo(UserAuthorities.admin)
@UseGuards(JwtAuthGuard)
@Get("/your-route")

这似乎是装饰器在 TypeScript 中工作方式的结果。

于 2021-03-04T13:35:27.137 回答