【问题标题】:Expire the JWT Token on logout in Spring Boot REST API在 Spring Boot REST API 中注销时使 JWT 令牌过期
【发布时间】:2019-07-20 01:35:12
【问题描述】:

当用户单击注销按钮时,如何使 JWT 令牌无效?我做了一些研究,但我找不到任何好的实现。

【问题讨论】:

    标签: rest spring-boot jwt


    【解决方案1】:

    您无法找到任何“过期”JWT 的方法,因为没有这种方法。可以说是JWT的缺点。

    如果token 被泄露,那么这是一个大问题。如果您需要使令牌/会话无效,您可能需要考虑其他身份验证机制。

    “无效”此类令牌的唯一方法是在后端使用其他 secret 密钥 - 这显然是一个非常可怕的想法!

    但是,如果您正在寻找一种在前端“注销”用户的方法,只需从存储中清除 JWT。 (不过,如果该用户复制了令牌,他将能够针对 rest api 执行请求)。

    【讨论】:

    • 您能否建议任何好的身份验证机制来使用 spring boot rest api 实现,这将允许无效和刷新令牌属性。
    • 这是一个非常广泛的话题,需要根据要求进行讨论/考虑。有许多机制,每种机制都有其优点和缺点。会话、基本身份验证、OAuth、JWT 等等。您需要阅读它们中的每一个,然后在收集一些知识后做出决定。
    • 这个答案不正确。有很多方法,而且非常简单,请查看我的答案。
    【解决方案2】:

    一种选择是只拥有一个bannedUsers 表。您甚至可以缓存此表。如果用户帐户遭到入侵,您可以将他们添加到表中,直到他们的令牌过期。每次都会查找(除非已缓存),但表上很可能总是有 0 条记录,因此速度会非常快。

    【讨论】:

      【解决方案3】:

      在与@RonOhRob 相同的行中,我建议使用jti (JWT ID) 声明。此声明为 JWT 提供了唯一标识符。

      您的 JWT 有效负载如下所示:

      {
          "iss": "example.com",
          "iat": "1300819080",
          "exp": "1300819380",
          "jti": "123e4567-e89b-42d3-a456-556642440000",
          "username": "mneri"
      }
      

      当 JWT 手动过期时,您会将 jti 插入黑名单。该值应保留在表中,直到令牌自然到期。现在,对于每个请求,还应该检查表内是否有jti;如果发现访问被拒绝。

      如果用户想要使他的所有令牌过期,还有另一个涉及iat (Issued At) 声明的简单策略:将deny_before 字段添加到user 表并注册expire_all API 调用的日期。和以前一样,您必须为每个请求添加检查。

      有关如何将 JWT 集成到 Spring 中的完整参考,请查看 JavaBrain's video。 视频中的人正在使用jjwt,但我推荐auth0's java-jwt 库,根据我的口味,它提供了更好的界面:

      JWT.create()
         .withJWTId(UUID.randomUUID().toString())
         .withIssuer(ISSUER)
         .withIssuedAt(issueDate)
         .withExpiresAt(expireDate)
         .withClaim("username", user.getUsername())
         .sign(Algorithm.HMAC256("secret"));
      

      现在,在你的JWTFilter

      JWTVerifier verifier = JWT.require(ALGORITHM).withIssuer(ISSUER).build();
      DecodedJWT decoded = verifier.verify(jwt);
      
      if (blacklistService.find(jwt.getId())) {
          throw new JWTVerificationException();
      }
      
      User user = userService.loadByUsername(jwt.getClaim("username").asString());
      
      if (user.getDenyBefore() != null && user.getDenyBefore().compareTo(jwt.getIssuedAt()) > 0) {
          throw new JWTValidationException();
      }
      

      【讨论】:

      • 好吧,它不会使令牌本身无效。这是一个黑名单。这是另一回事。当然,在某些情况下它可以是一个解决方案,但这本身并不是失效。
      猜你喜欢
      • 2021-03-11
      • 2021-09-04
      • 2020-02-20
      • 2021-03-03
      • 2016-04-01
      • 2021-07-23
      • 2018-02-19
      • 2019-07-21
      • 2016-10-23
      相关资源
      最近更新 更多