我在我的 nestJS 应用程序(使用 authGuard)中使用了 passport-jwt 身份验证策略,如何访问我的控制器中的令牌有效负载?

Posted

技术标签:

【中文标题】我在我的 nestJS 应用程序(使用 authGuard)中使用了 passport-jwt 身份验证策略,如何访问我的控制器中的令牌有效负载?【英文标题】:I'm using a passport-jwt auth strategy in my nestJS app (with authGuard), how to get access to the token payload in my controller? 【发布时间】:2019-08-29 09:37:34 【问题描述】:

我正在尝试访问受 AuthGuard 保护的路由中的 jwt 有效负载。

我正在使用passport-jwt,令牌有效负载是用户的电子邮件。

我可以通过运行下面的代码来实现:

import 
    Controller,
    Headers,
    Post,
    UseGuards,
 from '@nestjs/common';
import  JwtService  from '@nestjs/jwt';
import  AuthGuard  from '@nestjs/passport';

@Post()
@UseGuards(AuthGuard())
async create(@Headers() headers: any) 
    Logger.log(this.jwtService.decode(headers.authorization.split(' ')[1]));

我想知道是否有更好的方法?

【问题讨论】:

旁注:创建Logger 的实例比静态使用它更好。看到这个答案:***.com/a/52907695/4694994 【参考方案1】:

您的JwtStrategy 有一个validate 方法。在这里您可以访问JwtPayload。此方法的返回值将附加到请求中(默认在属性user 下)。所以你可以在这里从有效载荷中返回你需要的任何东西:

async validate(payload: JwtPayload) 
  // You can fetch additional information if needed 
  const user = await this.userService.findUser(payload);
  if (!user) 
    throw new UnauthorizedException();
  
  return user, email: payload.email;

然后通过注入请求在你的控制器中访问它:

@Post()
@UseGuards(AuthGuard())
async create(@Req() request) 
    Logger.log(req.user.email);

您可以通过创建自定义装饰器使这更方便:

import  createParamDecorator  from '@nestjs/common';

export const User = createParamDecorator((data, req) => 
  return req.user;
);

然后注入@User 而不是@Req

【讨论】:

我认为您不需要在 validate 函数中调用 validateUser(payload)。此时您的有效载荷已经有效,并由Passport 解码。您应该简单地返回新对象return user, email: payload.email; 就像在文档中一样:“一个“验证回调”,你告诉 Passport 如何与你的用户存储(你管理用户帐户的地方)交互。在这里,你验证一个用户存在(和/或创建新用户),以及他们的凭据是否有效。如果验证成功,Passport 库希望此回调返回完整用户,如果失败则返回 null(失败定义为用户是未找到,或者在本地护照的情况下,密码不匹配)。” docs.nestjs.com/techniques/authentication 对于其他策略,是的,但对于 JWT,它不是必需的,因为您的令牌已经过签名和验证。请参阅该文档的后面部分,了解为什么您不必在此处再次验证用户。 是的,这是正确的,您不需要再次验证令牌本身。但是,您可能希望使用该挂钩来获取附加数据以将其附加到请求中。或者,如果您有一个长期存在的令牌(在大多数情况下可能不推荐使用),您可能需要检查用户是否仍然存在、是否被列入黑名单等。我已经编辑了答案以包含您的观点。 参数装饰器应该使用执行上下文来实现:import createParamDecorator, ExecutionContext from '@nestjs/common'; export const User = createParamDecorator( (data: any, ctx: ExecutionContext) => const request = ctx.switchToHttp().getRequest(); return request.user; , )

以上是关于我在我的 nestJS 应用程序(使用 authGuard)中使用了 passport-jwt 身份验证策略,如何访问我的控制器中的令牌有效负载?的主要内容,如果未能解决你的问题,请参考以下文章

有效的 JWT 对 NestJS 守卫无效

NestJS 在 e2e 测试中模拟 JWT 身份验证

NestJS Swagger - 如何声明多选枚举字段?

nginx和nestjs认证部分之间的错误

我可以在我的 graphql 查询中访问请求标头,在 nestjs 中吗?

nestjs 是不是支持 graphql 片段?