由于夏令时,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 毫秒内。由于 exp
和 iss
值是紧接着彼此生成的,因此 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);
您仅有的两个解决方案是:
更改您的报告,以便使用 UTC(即 epoch unix 时间)而不是基于本地时间。从技术角度来看,这是更可取的解决方案,因为它是一个全球标准,包括大多数共享服务器和数据源;无需担心夏令时;你仍然可以让你的报告计算当地时间。
或者,查找或添加可靠的 '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 是您的首选解决方案,因为准确性和标准化更加直接。
如果没有丢失的小时数或增加的小时数,此测试通常全年都会通过。但现在这很麻烦。我们正在验证到期日期 getExp()
减去 7 天,在发行日期 getIss()
的 10 毫秒内。由于 exp
和 iss
值是紧接着彼此生成的,因此 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);
您仅有的两个解决方案是:
更改您的报告,以便使用 UTC(即 epoch unix 时间)而不是基于本地时间。从技术角度来看,这是更可取的解决方案,因为它是一个全球标准,包括大多数共享服务器和数据源;无需担心夏令时;你仍然可以让你的报告计算当地时间。
或者,查找或添加可靠的 '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 是您的首选解决方案,因为准确性和标准化更加直接。