JWT中的类强制转换异常

时间:2018-04-22 10:32:29

标签: java spring-boot jwt

我正在使用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;
}

解码令牌:

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

2 个答案:

答案 0 :(得分:4)

我建议将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
  

在这里,杰克逊发现5小到足以适应整数和   所以解开它,而不是预期的长。

     

更糟糕的是,当一个值足够大时(≥   2 ^ 31),杰克逊将切换到龙,因此总是天真地编码   get() - s整数将停止工作:

但是,问题已在this pull request中修复,并且可在较新发布的jwt库版本中找到。

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

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

希望能解决您的问题。

答案 1 :(得分:0)

令牌创建文件从底部开始的第3行&#34; .longvalue()&#34;。 我认为您应该尝试更改字段类型&#34; business AccountId&#34; to Long