JWT 中的类转换异常

Nil*_*tta 4 java jwt spring-boot

我正在使用JwtBuilder. 但是在使用键提取值时,它给出了ClassCastException. 为了更好地理解代码片段,提供如下:

令牌创建:

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;
}
Run Code Online (Sandbox Code Playgroud)

解码令牌:

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;
}
Run Code Online (Sandbox Code Playgroud)

例外:

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

jwt版本:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.6.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

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

Rea*_*hed 6

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

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

该问题在此处被报告为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
Run Code Online (Sandbox Code Playgroud)

在这里,Jackson 发现 5 小到足以放入 Integer 中,因此将其解组,而不是预期的 Long。

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

但是,该问题已在此拉取请求中得到修复,并且在 jwt 库的较新发布版本中可用。

更新库后,您无需RequiredTypeException使用以下代码即可获得正确的值。

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

希望能解决您的问题。