问题描述
我使用护照,想按角色保护几条路线。 看起来守卫调用了2次。起初它记录用户未定义。第二次它记录用户正确。我做错了什么?查看实现截图。
解决方法
守卫第一次运行来自全局绑定守卫
{
provide: APP_GUARD,useClass: RoelsGuard
}
由于这是一个全局守卫,它将是请求链中调用的第一个守卫(并且因为没有其他守卫)。您的 RolesGuard
正在查看由 req.user
分配的 passport
属性;在 NestJS 中,这通常由 AuthGuard
完成,它会在后台调用 passport.authenticate()
。那里的代码有点复杂,所以现在相信我。
如上所述,由于您绑定守卫的方式,执行看起来像 RolesGuard (global)
、JwtAuthGuard (route level)
、RolesGuard (route level)
。第二个路由级别的守卫,你的第二个 RolesGuard
在 JwtAuthGuard
之后运行,所以它可以像你期望的那样访问 req.user
。
现在,您可能会问的下一个问题是“我该如何解决这个问题?”过去我为此所做的是我已经绑定了我的 JwtAuthGuard
(或类似的)全局并在 RolesGuard
之前运行它,但添加了检查元数据是否应该路由授权保护与否。使用装饰器,我们可以将元数据添加到类和路由处理程序中(这就是 Nest 最初能够做的事情),并通过 ExecutionContext
方法中的 canActivate
从守卫中读取它。您也可以将 Nest 的 Reflector
注入到守卫类中,并进行 this.reflector.getAllAndMerge<boolean>('SHOULD_SKIP_AUTH',[context.getHandler(),context.getClass()])
之类的检查。从理论上讲,这将返回您通过类或路由处理程序级别的装饰器设置的布尔值,如果它返回 true
(即您应该跳过身份验证),那么请求保护可能会短路到 {{ 1}} 并让请求自行移动。