服务器与客户端时间不同步会导致expires失效,因其依赖客户端绝对时间比对;时区错误会进一步放大偏差;cache-control的max-age更可靠,建议新项目优先使用,并通过服务端时间戳检测偏差后降级为短max-age。

服务器与客户端时间不同步会直接导致 Expires 属性失效或行为异常,这不是配置错误,而是浏览器按本地时间解析该字段的固有机制决定的。
Expires 依赖客户端绝对时间,偏差即失效
Expires 是一个 GMT 格式的绝对时间点(如 Wed, 09 Oct 2024 00:00:00 GMT),浏览器完全用自身系统时间去比对它。一旦客户端时间比服务器时间快,哪怕只快 1 分钟,而 Expires 设的是 5 分钟后,实际在浏览器看来已是“过去的时间”,Cookie 就不会被持久化,退化为会话 Cookie;若客户端时间快几小时,该 Cookie 可能从写入那一刻起就被视为过期,根本不存入磁盘。
时区错乱进一步放大问题
即使时间戳数值正确,若客户端时区设置错误(比如设备设为 GMT+9 但实际在 GMT+0 区域),toUTCString() 或服务端生成的 GMT 时间串可能被错误解析。例如:服务器返回 Expires=Fri, 12 Sep 2026 08:00:00 GMT,而用户手机时区误设为 GMT+8,系统可能把它当作本地时间再转成 GMT,导致最终比对基准偏移 8 小时。
对比 Cache-Control 的相对性更可靠
- Expires 是 HTTP/1.0 遗留方案,强依赖两端时间一致,脆弱性高
- Cache-Control 的 max-age 是以秒为单位的相对值(如
max-age=3600),浏览器内部用当前时间 + 秒数计算过期点,只要本地时间不严重失准,误差可控 - 当两者共存时,max-age 优先级高于 Expires,建议新项目默认使用 max-age
服务端无法规避,但可主动识别和降级
你不能强制用户校准手机,但可以在关键流程中加入时间偏差检测:
- 登录成功响应体中附带标准服务器时间戳(如
{"server_time": 1747645380}) - 前端用
Date.now()与之比对,差值超 ±300 秒即标记为高风险用户 - 对该类用户,Cookie 设置弃用 Expires,改用较小 max-age(如 300 秒),并配合后端短 TTL + 静默续期











