【问题标题】:Class cast exception in JWTJWT 中的类转换异常
【发布时间】:2018-10-02 13:07:58
【问题描述】:

我正在使用JwtBuilder 创建一个令牌字符串。但是在使用键提取值时,它给出了ClassCastException。为了更好地理解代码 sn-p 提供如下:

令牌创建:

private JwtBuilder getJwtBuilder(
        String jti,
        Long issuedAt,
        Long expiredAt,
        Long businessAccountId,
        Long consumerAccountId,
        String deviceId
) {
    JwtBuilder builder = Jwts.builder();
    builder.setIssuer("SO");
    builder.setSubject(TokenConstant.TOKEN_SUBJECT);
    builder.setId(jti);
    builder.setIssuedAt(new Date(issuedAt));
    builder.setExpiration(new Date(expiredAt));
    builder.claim(TokenConstant.BUSINESS_ACCOUNT_ID, businessAccountId);
    builder.claim(TokenConstant.DEVICE_ID, deviceId);
    builder.signWith(SignatureAlgorithm.HS512, secretKey);
    return builder;
}

解码令牌:

private JsonWebToken decodeToken(String jsonWebToken) {
    try {
        Jws<Claims> map = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jsonWebToken);
        Claims claims = map.getBody();
        return getJsonWebTokenFromClaims(claims);
    } catch (SignatureException | MalformedJwtException e) {
        throw new InvalidTokenException(e.getMessage());
    }
}

private JsonWebToken getJsonWebTokenFromClaims(Claims claims) {
    JsonWebToken token = new JsonWebToken();
    token.jti = claims.getId();
    token.expirationTime = claims.getExpiration().getTime();
    token.issuedAt = claims.getIssuedAt().getTime();
    token.deviceId = (String) claims.get(TokenConstant.DEVICE_ID);
    token.businessAccountId =  (Long) claims.get(TokenConstant.BUSINESS_ACCOUNT_ID);
    return token;
}

例外:

2018-04-23 10:27:04.476 错误 b.c.i.s.c.MyExceptionHandler - 应用程序错误:{} java.lang.ClassCastException:java.lang.Integer 不能转换为 java.lang.Long

jwt 版本:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.6.0</version>
</dependency>

如您所见,我的代码在将 Integer 类型值转换为 Long 类型时出错。我无法理解,为什么Object 类型会隐式转换为Integer

【问题讨论】:

  • 请直接发布您的代码而不是截图,点击4个链接查看您的代码相当麻烦。请阅读How to Ask
  • 按照您的建议更新。

标签: java spring-boot jwt


【解决方案1】:

令牌创建文件从底部开始的第 3 行您正在执行“.longvalue()”。 我认为您应该尝试将字段“business AccountId”的类型更改为 Long

【讨论】:

  • builder.claim 令牌创建文件底部的第 4 行期望什么。你只需要传递那种类型的争论。
  • 粘贴最新代码和错误。 builder.claim() 只不过是 的映射。所以,我放什么类型的值并不重要。
【解决方案2】:

我建议将您的 jwt 依赖项的版本升级到版本 0.9.0

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>

此问题在此处报告为 an issue in Github,表示根据设置为声明的较小值自动绑定到数据类型。我正在复制该问题的确切陈述以进行详细说明。

  String claimName = "long"
  Long claimVal = new Long(5)
  String compact = Jwts.builder().setClaims([(claimName): claimVal]).compact();
  Claims claims = Jwts.parser().parse(compact).body as Claims
  // `claims.get` throws `RequiredTypeException`
  assert claims.get(claimName, Long) == claimVal

在这里,Jackson 发现 5 小到可以放入 Integer 和 所以解组到它,而不是预期的 Long。

更糟糕的是,当一个值足够大时(≥ 2^31), Jackson 将切换到 Long 并且总是天真地编码 get()-s Integer 将停止工作:

不过,该问题已在 this pull request 中得到修复,并且在 jwt 库的较新发布版本中可用。

更新库后,您可以使用以下代码在没有RequiredTypeException 的情况下获得正确的值。

// businessAccountId is declared as Long I guess
token.businessAccountId = claims.get(TokenConstant.BUSINESS_ACCOUNT_ID, Long.class);

希望能解决您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    相关资源
    最近更新 更多