使用 nestJS 注销 JWT

我正在使用 JWT passaport 登录模块:

 async validateUser(userEmail: string, userPassword: string) {
    const user = await this.userService.findByEmail(userEmail);
    if (user && user.password === userPassword) {
      const { id, name, email } = user;
      return { id: id, name, email };
    }else {
      throw new UnauthorizedException({
        error: 'Incorrect username or password'
      });
    }
  }

  async login(user: any) {
    const payload = { email: user.email, sub: user.id };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }

这部分正在运行。我的问题是:如何注销?我阅读了有关创建黑名单并将令牌添加到其中的信息,但是如何获取用户的访问令牌?

stack overflow Logout JWT with nestJS
原文答案
author avatar

接受的答案

关于基于令牌的身份验证,您应该了解的一点是它是无状态的。这意味着即使服务器也不会跟踪哪些用户已通过身份验证,就像基于会话的身份验证一样。因此,您无需在服务器端执行任何操作即可“注销”用户。您只需删除客户端上的 tJWT 令牌。如果您向服务器应用程序发出请求,但没有有效的 JWT 令牌,它将被视为用户未登录。


答案:

作者头像

通常,当发送注销请求时,应该存在 Authorization 标头,因此您可以从那里获取令牌。然后您可以将令牌保存到数据库的限制列表表中。

作者头像

当用户单击“注销”btn 时,您应该发送一个请求,该请求附加了带有不记名令牌的授权标头。在后端,您需要提取标头并将令牌推送到黑名单令牌(作为您的解决方案)。基本上,您只需要在客户端删除令牌,这很容易做到,但在最坏的情况下,当令牌被黑客窃取时,您的令牌仍然有效。使用黑名单令牌更安全,但可能会导致性能问题和可扩展性。什么是最好的解决方案?这取决于你。

作者头像

读取 Nestjs 执行上下文,从请求标头中获取令牌,并从 JWT 验证此令牌。

everything defines in the NESTJS link

//这里我们检查头部中的令牌是否有效或未过期

const tokenVarify = await this.jwtService.verify(token);
作者头像

我的想法是让每个生成新令牌的白名单并在用户注销时将其删除。因此,您还需要检查每个具有令牌访问权限的用户是否存在于白名单或注释中

作者头像

您必须使用以下命令将过期令牌刷新到 1 毫秒: https://webera.blog/how-to-implement-refresh-tokens-jwt-in-nestjs-b8093c5642a9

作者头像

实际上有一个解决方法,但不是那么简单!这个想法是跟踪已注销用户的令牌(使用某种黑名单)并针对该黑名单查询提供的令牌。

总而言之,您可以按照以下 4 个步骤进行操作:

1.设置合理的token过期时间

  1. 注销时从客户端删除存储的令牌
  2. 拥有不再活跃的代币数据库​​,这些代币还有一些生存时间
  3. 在每个授权请求上查询黑名单提供的令牌

详细解释可以查看这个帖子: medium

这个 youtube 视频 Code with Vlad 中提供了如何实现的指南,还有 github 源代码 nestjs-jwts 。我关注了这个视频并实现了自己。