在 UTC 中使用过期日期时 JWT 过期不起作用

我正在使用jjwtjwt 令牌创建。使用本地系统时间设置到期日期时一切正常,即


日期 expDate = new Date(new Date().getTime() + 180000); //java.util.日期


但我尝试使用 UTC 格式日期时间并使用相同的 3 分钟到期日期签署 jwt 令牌。现在它正在抛出ExpiredJwtException,尽管我在创建令牌后立即进行验证。我正在使用 SimpleDateFormat 将时区设置为 utc。这是我在 java 中使用 jjwt 创建令牌的代码:


    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    Date expDate, issDate;

    try {

        expDate = (Date) simpleDateFormat.parse(sdf.format(new Date().getTime() + 180000));

        issDate = (Date) simpleDateFormat.parse(sdf.format(new Date().getTime()));

        JwtBuilder builder = Jwts.builder()

                .setExpiration(expDate)

                .setIssuedAt(issDate)

                .setId(id)

                .signWith(signingKey, signatureAlgorithm);

        jwtToken = builder.compact();

    } catch (ParseException ex) {

    }

令牌已成功创建。我也可以在线验证内容。expDate 比 issDate 早 3 分钟。我还在通过传递创建的令牌创建令牌后立即调用验证令牌的方法。我的验证方法有:


    try {

        Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token);

        log.info("jwt verification success");

    } catch (ExpiredJwtException exJwt) {

        log.info("expired jwt : \n{}", exJwt.getMessage());

    } catch (JwtException e) {

        log.info("tampered jwt");

    }

但我越来越ExpiredJwtException。错误是


expired jwt :JWT 在 2019-05-17T01:24:48Z 过期。当前时间:2019-05-17T07:06:48Z,相差20520836毫秒。允许的时钟偏差:0 毫秒。


从我的日志来看,此时我的token中的签发日期和到期日期是:


issued date is: 2019-05-17T07:06:48.000+0545

expiry date is: 2019-05-17T07:09:48.000+0545

这是怎么回事?谢谢你的帮助。


慕田峪9158850
浏览 115回答 1
1回答

呼啦一阵风

这里不需要SimpleDateFormat,as表示自Unix EpochDate以来的毫秒数,即 1970 年 1 月 1 日午夜(UTC)。然而,可能导致混淆的是方法,toString()因为它在生成表示该值的字符串时应用 JVM 的默认时区。由于您担心 UTC,让我提醒您注意协调世界时 (UTC) 实际上是什么:它是一个时间标准(而不是时区),它由高精度原子钟和地球自转决定。UTC 时间标准经过多次调整,直到 1972 年引入闰秒以使 UTC 与地球自转保持一致,地球自转并不完全均匀,而且不如原子钟精确。随着地球自转速度的减慢,我们不得不时不时地在各处插入闰秒:虽然 的内部值Date旨在反映 UTC,但由于那些闰秒,它可能不会完全这样做。Java 8 和日期和时间的新 API即使Date在涉及 UTC 时适合您的需求,您也应该避免使用它。现在是遗留类。Java 8为基于 ISO 日历系统的日期、时间、瞬间和持续时间引入了新的 API 。最接近的等价物Date是Instant代表时间戳,UTC 时间线上的时刻。要以 UTC 格式捕获当前时刻,您可以使用以下命令:Instant.now();              // Capture the current moment in UTC您可以使用以下内容来获取表示此类值的字符串:Instant.now().toString();   // 2019-05-17T12:50:40.474Z此字符串根据ISO 8601进行格式化,其中Z指示给定时间为 UTC。与 JJWT 的互操作性对于尚不支持类型的JJWT 的互操作性java.time,您可以创建Datefrom的实例Instant:Date.from(Instant.now());   // Convert from modern class to legacy class这是一个演示如何发布和验证令牌的测试:@Testpublic void shouldMatchIssuedAtAndExpiration() {    Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);    Instant issuedAt = Instant.now().truncatedTo(ChronoUnit.SECONDS);    Instant expiration = issuedAt.plus(3, ChronoUnit.MINUTES);    log.info("Issued at: {}", issuedAt);    log.info("Expires at: {}", expiration);    String jws = Jwts.builder()            .setIssuedAt(Date.from(issuedAt))            .setExpiration(Date.from(expiration))            .signWith(key)            .compact();    Claims claims = Jwts.parser()            .setSigningKey(key)            .parseClaimsJws(jws)            .getBody();    assertThat(claims.getIssuedAt().toInstant(), is(issuedAt));    assertThat(claims.getExpiration().toInstant(), is(expiration));}对于上面的示例,我使用了 JJWT 0.10.5 以及文档中列出的依赖项。如果您需要,上面的代码是用以下import语句编写的:import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import io.jsonwebtoken.security.Keys;import lombok.extern.slf4j.Slf4j;import org.junit.Test;import java.security.Key;import java.time.Instant;import java.time.ZoneOffset;import java.time.temporal.ChronoUnit;import java.util.Date;import static org.hamcrest.CoreMatchers.is;import static org.junit.Assert.assertThat;
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java