Nestjs 角色守卫调用 2 次并首先让用户未定义

问题描述

我使用护照,想按角色保护几条路线。 看起来守卫调用了2次。起初它记录用户未定义。第二次它记录用户正确。我做错了什么?查看实现截图。

roles guard

app module

usage

解决方法

守卫第一次运行来自全局绑定守卫

{
  provide: APP_GUARD,useClass: RoelsGuard
}

由于这是一个全局守卫,它将是请求链中调用的第一个守卫(并且因为没有其他守卫)。您的 RolesGuard 正在查看由 req.user 分配的 passport 属性;在 NestJS 中,这通常由 AuthGuard 完成,它会在后台调用 passport.authenticate()。那里的代码有点复杂,所以现在相信我。

如上所述,由于您绑定守卫的方式,执行看起来像 RolesGuard (global)JwtAuthGuard (route level)RolesGuard (route level)。第二个路由级别的守卫,你的第二个 RolesGuardJwtAuthGuard 之后运行,所以它可以像你期望的那样访问 req.user

现在,您可能会问的下一个问题是“我该如何解决这个问题?”过去我为此所做的是我已经绑定了我的 JwtAuthGuard(或类似的)全局并在 RolesGuard 之前运行它,但添加了检查元数据是否应该路由授权保护与否。使用装饰器,我们可以将元数据添加到类和路由处理程序中(这就是 Nest 最初能够做的事情),并通过 ExecutionContext 方法中的 canActivate 从守卫中读取它。您也可以将 Nest 的 Reflector 注入到守卫类中,并进行 this.reflector.getAllAndMerge<boolean>('SHOULD_SKIP_AUTH',[context.getHandler(),context.getClass()]) 之类的检查。从理论上讲,这将返回您通过类或路由处理程序级别的装饰器设置的布尔值,如果它返回 true(即您应该跳过身份验证),那么请求保护可能会短路到 {{ 1}} 并让请求自行移动。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...