“ 阅读本文大概需要 3 分钟。”
最近写了一个 API Token 的校验服务,想要增加时效性控制,比如一个 API,超过一段时间(比如 10s)之后,用同样的参数再请求就会被服务器禁掉,无法获取正常数据,这样可以保证数据的安全。
怎么增加时效性控制呢?加一个时间的信息就好了,我们可以把时间信息包含在一个 API URL 的额外的参数 token 里面。比如最简单的,把前端获取的时间戳进行 Base64 编码之后作为 token,这个 token 会传递给后端,后端会对获取到的 token 进行解码,对获取到的时间戳进行校验,如果 Token 里面的时间戳和 Server 端的时间戳相差不超过一定的时间阈值(比如 10s),那就正常返回结果。如果超过一定的时间,服务器就直接返回 401 状态码,不会返回正常数据,这样可以保证接口的实时性,进一步保证安全。
但是现在遇到了一个问题,我一开始把二者的时间差阈值设置成了 10 秒,在本地测试没有问题,完全 OK,接口可以正常获取数据。怪的问题来了,我把项目部署到服务器上,发现怎么着都不行,一直返回 401 状态码。经过调试发现是前后端在同一时间获取到的时间戳是不一样的,足足相差了有 16 秒,服务器获取的时间戳比客户端慢了 16s,这导致在同一时刻二者并不能达到阈值条件,导致接口一直不能获取正常数据。
这到底是是为什么?为啥部署到服务器上之后,时间戳差别这么大呢?
原因
其实原因在于,服务器没有对时间进行校准,时间有偏差,我也是醉了。。
为了校准时间,我搜寻了过一些相关的知识,找到了 NTP 服务器相关问题,这里将时间和 NTP 相关问题记录一下。
时间
接下来我们先看看时间和时区相关的内容吧。
时区
按照常识来说,一天被划分 24 小时,近似球体的地球是 360 度,所以我们使用经纬度为坐标,将全球划分为 24 个时区。
国际上规定,每隔 15 度划分一个时区,全球可分为 24 个时区。以本初子午线为基准,从西经 7.5° 至东经 7.5°,划分为中时区,或叫零时区,每时区区时相差一小时,东加西减。
下面看看图,估计大家地理上也学过。
东八区
格林尼治时间为世界标准时间,即中时区的时间。又因为东半球(格林尼治以东)的时间比较早,中国的经度在 120°E,是位于第八个时区,所以我们是在东八区,我们国家统一也用的东八区时间作为北京时间。
UTC 时间
UTC,全称为 Coordinated Universal Time,表示协调通用时间,根据原子振荡周期所计算的物理时钟,这种计算方式对于时间的计算误差时很小的。
GMT 时间
GMT,全称为 Greenwich Mean Time,表示的是格林尼治时间,是根据地球的自转周期计算的标准时间,由于各种不稳定因素的影响,计时不是很理想。
软件时钟
表示的是 Linux 操作系统从 1970 年 01 月 01 日(中时区)开始计算的时间。
硬件时钟
主机硬件上面的时钟,主要是 BIOS 内部时间的记录的时间。
时间戳
时间戳是指格林威治时间 1970 年 01月 01日 00 时 00 分 00 秒(北京时间 1970 年 01 月 01 日 08 时 00 分 00 秒)起至现在的总毫秒数。
时间戳不区分时区,全世界一样。
NTP 服务器
了解了一些时间的定义之后,我们再来了解下 NTP 服务器相关的内容。
NTP 服务器是干嘛的?
来看看官方定义:
NTP(Network Time Protocol)服务器,是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS 等等)做同步化,它可以提供高精准度的时间校正(LAN 上与标准间差小于 1 毫秒,WAN 上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。时间按 NTP 服务器的等级传播。按照离外部 UTC 源的远近把所有服务器归入不同的 Stratum(层)中。
懂了吧,NTP 服务器就是提供时间信息的,我们通过 NTP 服务器可以获取当前时间。
NTP 服务器怎样同步时间
那世界上肯定有很多 NTP 服务器吧,它们怎么同步时间的呢?
下面我们再来看看 NTP 服务器的特性:
NTP 提供准确时间,首先要有准确的时间来源,这一时间应该是国际标准时间 UTC。NTP 获得 UTC 的时间来源可以是原子钟、天文台、卫星,也可以从 Internet 上获取。这样就有了准确而可靠的时间源。时间按 NTP 服务器的等级传播。按照离外部 UTC 源的远近将所有服务器归入不同的 Stratum(层)中。Stratum-1 在顶层,有外部 UTC 接入,而 Stratum-2 则从 Stratum-1 获取时间,Stratum-3 从 Stratum-2 获取时间,以此类推,但 Stratum 层的总数限制在 15 以内。所有这些服务器在逻辑上形成阶梯式的架构相互连接,而 Stratum-1 的时间服务器是整个系统的基础。 计算机主机一般同多个时间服务器连接, 利用统计学的算法过滤来自不同服务器的时间,以选择最佳的路径和来源来校正主机时间。即使主机在长时间无法与某一时间服务器相联系的情况下,NTP 服务依然有效运转。 为防止对时间服务器的恶意破坏,NTP 使用了识别(Authentication)机制,检查来对时的信息是否是真正来自所宣称的服务器并检查资料的返回路径,以提供对抗干扰的保护机制。
所以,可以看到,经过 Stratum 的层层传播,各个 NTP 服务器实现了时间同步。
各个 NTP 服务器的时间基本都是很精确的,我们可以从 NTP 服务器来获取时间,但由于网络时延问题,可能相差一点点。
NTP 服务器列表
NTP 全球太多太多了,比如全球、每个大洲、大公司、高校都会有自己的 NTP 服务器。
例如:
•全球:pool.ntp.org•亚洲:asia.pool.ntp.org•北美洲:north-america.pool.ntp.org•中国教育网:edu.ntp.org.cn•上交:ntp.sjtu.edu.cn•微软:time.windows.com•苹果:time.apple.com
等等,当然我们也可以自己设置自己想用的 NTP 服务器。
NTP 服务器校准
那么回到我的问题,我的服务器的时间没有经过校准,导致时间差距这么大。所以我可以使用 NTP 服务器对时间进行校准就好了。
服务器是 Ubuntu 系统,校准流程如下。
首先服务器上安装 ntpdate:
代码语言:javascript复制sudo apt install ntpdate
然后校准时间,输入任意一个 NTP 服务器地址就行了:
代码语言:javascript复制sudo ntpdate time.apple.com
经过校准之后,发现时间就一致了,问题解决。
参考
•https://baike.baidu.com/item/中时区/339115•https://baike.baidu.com/item/NTP服务器/8633994•https://blog.csdn.net/qq_36294875/article/details/79491614•https://segmentfault.com/q/1010000021645848/a-1020000021645987•https://www.weibo.com/ttarticle/p/show?id=2309403955443172016290
崔庆才丨静觅
隐形字
同名公众号「崔庆才丨静觅」