技术解析

前端要以服务器的时间为准,有啥好用的库吗?
0
2021-08-10 00:27:56
idczone

场景是大量客户端电脑时间都不准,也没有时间同步,只能在程序里请求后端时间接口获取真实时间。

现在想法是程序只取一次服务器时间,然后在客户端模拟一个时间出来,关键要能支持 new Date 获取这个模拟时间,而且这个模拟时间能一直自动继续走。

这样的需求有啥好用的库吗?


前端会 像服务器一样时刻运行着?

加个 https 。如果他们时间不准就用不了

我意思是程序运行的时候从服务器取一次时间

计算服务端与客户端时间戳的差值,保存在前端

如果客户端的时间和服务器是有差值但是差值不变
那么根据两者固定的差值计算

没有什么库,因为需要由服务端配合, 你的服务端可以是 java 的,c而客户端如果直接修改电脑时钟,又需要权限. 其实思路也非常简单, 自己实现好了. 服务端返回时间, 客户端本地时间和服务端时间做一个差值, 然后显示时间时,始终加上这个差值. 也不用什么定时同步, 客户端不会连续工作几十天,也不会几个小时就跑出几秒的误差

window.Date = function() {...}

轮询吧,一次差值不靠谱。因为本机时间除了用户修改外,本身也会跳变,具体可搜下闹钟失效之类的案例。

每次 api,都把服务器时间返回回去?
这个问题我也遇到过

response header 里面默认就带有服务器时间的,Date 字段,但是因为 CORS 的原因,你默认读不到,可以在服务器端配置一下 cors 头,你就可以读到了,这个时间再加上通信的时间,就比较准确了

实现个 ntp 算法

进来的时候 请求后端拿到服务器时间, 然后本地也 new Date, 做差值,
是有误差 但是差值是不变的.
后续只要 new Date + 差值 即可

response header +1

讲真,大部分项目 http 请求都是封装好的,拿不到 header
存差值比较合理

所有接口加个默认字段也行

存差值,多次按远近加权平均。

我们之前的方案是 websocket 走心跳,假如每五秒一次心跳,每次心跳服务端都返回服务端时间,前端拿到时间做每次校验修正,前端时间也时刻在走

通信的时间要怎么拿到呢?

据我了解,一些用户机器的时间不准,即使同步了时间,可能还是过一天差一点,过不几天又不准了。
这个要牵扯到 CPU 时钟之类的,连他的机器都无法准确计算时间,你通过 js 算法 sleep 计算时间只会更不准。
所以只有跟服务器通信才是王道,websocket 是最优解,轮训对服务器压力大,也可以通过 10-30 秒一轮询,计算一下和本机的差值,时间等于差值+他的本地时间。

开个 gRPC 服务,websocket 不适合这种场景,要与时俱进

https://github.com/enmasseio/timesyn
找到一个现成的库,不知道性能如何还没细看

还是传统的 websocket,应该轮询实现的

通信时间就用本地计时的差值就可以,至于精度,可以根据需求来呗,他的核心需求是客户端时间不准是因为没开 ntp 对时,所以估计是差异很大,需求可能只是要求一个跟服务器尽量统一的时间,如果精度要求不高,可以就用 Date 的差值其实也就可以了。如果需要精度高一些的,可以用 performance.now()

服务端渲染

很多网站都禁止时间不准的电脑访问,例如 y2b

自己的服务器,自己的前端,不需要 CORS 就可以读 headers

电脑时钟总是准的,存个基准时间比较差值呗

像 firebase 都会返回统一的服务器时间戳

淘宝这样同步时间的
acs.m.taobao.com/gw/mtop.common.getTimestamp/*

那以后移民火星的看不了片子了

时延和时间准确不一样哦。
说的应该是连接到 HTTPS 网站时加密通信失败带来的打不开

响应头上去取就可以了,后端配置下即可


这个是直接发一个 http GET 请求就可以了?然后在返回的结果里面把 data.t 取出来?
```
{"api":"mtop.common.getTimestamp","v":"*","ret":["SUCCESS::接口调用成功"],"data":{"t":"1616639029711"}}
```

自己的前端是什么概念? cors 是浏览器端的机制,只要用户还在使用正常的,版本不是特别老的浏览器,读取 header 就必须遵守 CORS,你自己尝试一下不难


试了一下,用 postman 客户端,http GET 可以成功。
但是,用 postwoman,在线版 /PWA 版本,都是 404 。 奇怪, 我已经用 CORS 插件禁止了呢。
```
Referrer Policy: strict-origin-when-cross-origin
```

你放心,等你移民火星的时候,火星上的互联网公司估计早都建好机房了 XD

是不是可以换个思路,让后端来做时间之类的东西,既然要服务器的时间,那么让后端接受到接口的时候自己建立时间对象

CORS 是 Cross-origin resource sharing,这里根本就不 Cross-origin,不受这个限制

我确定你没搞懂 CORS 里面的 Cross-Origin 指的什么场景,到底哪里会 Cross Origin,为什么要做这个限制。
https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header,注意这篇文章的标题:CORS-safelisted_response_header,点开链接看一下,然后再好好理解下 CORS 的本质。

我读了文章,试着理解一下
1. 当 A 站 的前端跨域访问 B 站的页面时,因为同源限制,读取的内容会被浏览器抛弃掉;
2. 此时,如果 B 站的后端确认这些内容不是用户的机密,可以配置一个 CORS 标志,使得 A 站的前端可以读取这个内容;
3. 文章说的是,即便配置了 CORS 标志,有些消息头仍然没有全部暴露给 A 站,这个过程会经历一个过滤器;
4. 这个过滤器默认放行文章所述的 6 种消息头;以及,这个放行策略可以由 B 站进行扩充
那么,回到问题,题主现在是 A 站的前端,需要从 A 站的响应里读取消息头,整个过程不需要跨域,所以不需要配置 CORS,自然更不需要管理 CORS-safelisted_response_header

所以我前面指出你就没理解对 CORS 的设计目的。CORS 是浏览器行为,是为了防止在浏览器端发生泄漏,服务端只是配合。那么浏览器端怎么发生泄漏呢?那就是 js,也就是如果某一个 js 执行了一段代码,读取到了**被认为**可能泄漏隐私的消息,这时候再发起一个到第三方的请求(可以是 js,也可以是 img ),就相当于把信息传递出去了,这个过程就被认为发生了泄漏。那么浏览器怎么做呢?其中一点就是限制了默认情况下 js 可以读取的 response header 的字段,也就是给你的文章里面的那 6 个,其他的,就得服务器端配合配置了才能由 js 读取到,这里面就包括了 date 字段。(另外不要弄错了,你通过开发人员工具是能读到的,cors 保证的是 js 代码读取不到)

我觉得您可能认为 CORS 会同时作用于同域和跨域,并认为 CORS 是浏览器权限控制的全部内容,事实就如其名字,仅仅用来管理跨域访问
对于同域消息头的访问,有这几个概念
https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name
这部分描述了哪些**请求**消息头是不能被脚本**修改**的
https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_response_header_name
这部分描述了哪些**响应**消息头是不能被脚本**修改**的
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/getAllResponseHeaders
这是与本文最相关的部分,描述了同域状态下,哪些消息头是不能被脚本**读取**的
事实上只有 Set-Cookie 和 Set-Cookie2 两个字段禁止读取,并不包含 Date
这里有一篇文章有比较详细的讲解
https://segmentfault.com/a/1190000004322487

按 2 楼说的 上 https 时间不对 用不了 前端就抛出个错误提示就好了。

你是对的,我之前的实验有问题,执行的 js 是从 cdn 上取的,相当于没有测试过同源的情况。不过考虑到现在服务部署的方式,很多时候资源就是从 cdn 部署的,并不能保证跟主站同源,这个 CORS 还是很有可能需要的(就像我遇到的情况),非常感谢你指出了我的盲区。

讨论也加深了我对这块的理解。不过还是有点问题,跨域不是指**网页**和**脚本**在不同的域下,不同来源的脚本只要加载到页面里,有一致的完整的权限
跨域指**网页**和脚本访问的另一个**网页**是不是在同一个域下,当跨域时,受 CORS 的策略的管理

恩,在发完之后我继续回忆了我测试的场景,应该是主站(静态页),cdn 加载 js,然后 API,三个独立的域名,js 试图读取的是 API 的 response 的 header 。

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服