由于夏令时,JWT 发行日期与到期日期检查失败。什么是全年无休的解决方案?

JWT Issue date vs. Expiration date check is failing due to daylight savings time. What's a year-round permanent solution?

如果没有丢失的小时数或增加的小时数,此测试通常全年都会通过。但现在这很麻烦。我们正在验证到期日期 getExp() 减去 7 天,在发行日期 getIss() 的 10 毫秒内。由于 expiss 值是紧接着彼此生成的,因此 10 毫秒是一个完全可以接受的增量,期望值介于两者之间。

但是现在可以理解的是,当 Java 日期代码在初始化新的 JWT 声明后调用 setExp() 时,他们现在可以理解一个小时的休息时间。

断言/测试代码:

       assertThat(claim.getExp()).isCloseTo(new DateTime(claim.getIss()).plusDays(7).toDate(), 10);

英文是这样写的:断言索赔的到期日期在索赔签发日期的 10 毫秒内 + 7 天。

一个直接的解决方法是将一个小时的毫秒值添加到允许的增量中,但我很好奇是否有更好的解决方案。

编辑:我相信我找到了问题所在。我们使用 ZonedDateTime.now():

初始化索赔签发日期和索赔到期日期
Claim claim = new Claim();
claim.setIss(Date.from(ZonedDateTime.now(ZoneId.of("UTC")).toInstant())); 
claim.setExp(Date.from(ZonedDateTime.now(ZoneId.of("UTC")).plusDays(7).toInstant()));

但是当我们使用 JODA 时间进行验证时,我们假设我们的本地夏令时规则。这显然会导致 GMT DST 与美国 DST 规则出现问题。

EDIT2:修复涉及 2 个单词并更新单元测试以遵守 UTC:

    assertThat(claim.getExp()).isCloseTo(new DateTime(claim.getIss(), DateTimeZone.UTC).plusDays(7).toDate(), 10);

您仅有的两个解决方案是:

  1. 更改您的报告,以便使用 UTC(即 epoch unix 时间)而不是基于本地时间。从技术角度来看,这是更可取的解决方案,因为它是一个全球标准,包括大多数共享服务器和数据源;无需担心夏令时;你仍然可以让你的报告计算当地时间。

  2. 或者,查找或添加可靠的 'dateadd' 类型的函数,将夏令时考虑在内。

令我惊讶的是,所有平台都没有该功能 built-in。诚然,DST 有一套令人困惑的 ever-evolving 规则集,它们是 region-specific(按大陆、国家和某些地区按 "state" 甚至 "county")...但是仍然。

目前,在北美大部分地区,夏令时:

  • 开始 三月的第二个星期日。 ("Spring Forward" 所以时钟从 01:59 变为 03:00)

  • 在 11 月的第一个星期日结束。 ("Fall Back" 从 01:59 到 01:00)

Windows API 具有计算 DST 是否有效的功能,但实际上,任何应用程序都不应允许应用程序显示,例如在北美:"Sunday March 11, 2018 02:30:00" 因为 那个时间不存在.

...不过,#1 是您的首选解决方案,因为准确性和标准化更加直接。