1 回答
TA贡献1802条经验 获得超6个赞
这里不需要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
,您可以创建Date
from的实例Instant
:
Date.from(Instant.now()); // Convert from modern class to legacy class
这是一个演示如何发布和验证令牌的测试:
@Test
public 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;
添加回答
举报