双方服务器时间戳不一致,导致凭证大概率过期
2026-05-08
我问:
现在遇到一个问题,我这里颁发的一个凭证,时间戳可能比对方超前,然后加上60,到他那里就出现了有效期不正确的提示,我该怎么弄?把过期时间改小?
AI答:
不要优先把过期时间“改小”。真正问题不是 60 秒太长,而是 双方服务器时间不一致。
你现在的问题本质是:
你的服务器时间:12:00:30 对方服务器时间:12:00:00 你生成 expireTime = 12:01:30 对方拿到后判断:这个凭证有效期还有 90 秒,超过允许的 60 秒 于是提示:有效期不正确
也就是说,对方不是觉得它“过期了”,而是觉得它“有效期太长”或“签发时间在未来”。
一、正确处理顺序
1. 第一优先级:校准服务器时间
这是根治方案。
在你的服务器上先看时间:
date timedatectl status
开启 NTP 自动校时:
sudo timedatectl set-ntp true
如果是 CentOS / Rocky / AlmaLinux,可以看:
chronyc tracking systemctl status chronyd
如果你的程序跑在 Docker 里,注意:
容器时间一般跟宿主机走,所以要校准宿主机时间,不是只看容器。
二、如果短期无法让双方时间完全一致,怎么兼容?
你可以做一个“时间回拨补偿”。
比如你发现你们服务器普遍比对方快 30 秒,那就不要用本机当前时间直接签发,而是:
签发基准时间 = 当前时间 - 30 秒 过期时间 = 签发基准时间 + 60 秒
也就是:
$ttl = 60; $clockOffset = 30; // 你方时间比对方快约 30 秒,就回拨 30 秒 $baseTime = time() - $clockOffset; $expireTime = $baseTime + $ttl; $payload = [ 'sub' => json_encode([ 'thirdparty' => 'norming', 'module' => 'SELFBUILT', 'tenantId' => $tenantId, 'creditCode' => $creditCode, 'expireTime' => $expireTime, 'nonce' => bin2hex(random_bytes(8)), ], JSON_UNESCAPED_UNICODE), 'iat' => $baseTime, 'exp' => $expireTime, ];
这样对方看到的是:
iat:更接近对方当前时间 expireTime:距离对方当前时间约 60 秒
比单纯把过期时间改小更稳。
三、为什么不建议直接把过期时间改小?
比如你直接从:
expireTime = 当前时间 + 60
改成:
expireTime = 当前时间 + 30
短期可能能过,但会带来两个问题:
第一,真实可用时间变短。网络慢一点、接口排队一下、重试一次,凭证可能就过期了。
第二,时间偏差一变又会失败。今天你们快 30 秒,明天快 45 秒,后天 NTP 恢复正常,它又不稳定了。
所以更好的做法是:
不是单纯缩短有效期,而是修正签发基准时间。
四、最好让对方加“时间容忍窗口”
如果能跟对方沟通,建议他们校验时允许一定时间误差,比如 ±60 秒或 ±120 秒。
正确校验逻辑应该类似:
iat 不能明显晚于对方当前时间,比如不能超过 now + 60 expireTime 不能早于对方当前时间,比如不能小于 now - 60 expireTime - iat 应等于或不超过 60 秒
不要死板地判断:
expireTime - 当前时间 必须小于等于 60 秒
因为这个判断天然怕服务器时间误差。
五、你们这个“诺明凭证”建议统一成这样
你之前那个 token 里有两个过期时间:
sub.expireTime:60 秒后 JWT 外层 exp:7 天后
这个不太好,容易导致对方系统校验逻辑分裂。
建议统一:
iat = 签发基准时间 exp = 签发基准时间 + 60 sub.expireTime = 签发基准时间 + 60
也就是外层 exp 和内层 expireTime 保持一致。
六、最终建议
你现在不要简单理解成“把过期时间改小”。
更准确的处理是:
1. 先校准你方服务器时间; 2. 如果短期仍有偏差,就做签发时间回拨补偿; 3. iat、exp、sub.expireTime 使用同一个基准时间; 4. 最好让对方加 60~120 秒 clock skew 容忍; 5. 如果偏差超过 60 秒,靠凭证参数硬调不可靠,必须校时。
你可以临时先这样改:
baseTime = time() - 30 expireTime = baseTime + 60
如果对方仍提示有效期不正确,再把 30 调成 45 或 60。但这只能算临时兜底,最终还是要把服务器时间同步好。
发表评论: