aws s3 presign s3://bucket/a.jpg --expires-in 600
curl -I "https://bucket.s3.amazonaws.com/a.jpg?X-Amz-Expires=600&..."

前端拿到的图片链接一小时后打开报 403,响应体里是 <Code>AccessDenied</Code>,细节写着 Request has expired。生成链接的服务和对象存储时间差了 6 分钟。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:预签名把过期时间写进签名,服务端按自己的时钟判断。有效期从签名那一刻算,X-Amz-Expires 单位是秒且有上限。两端时钟偏几分钟,短有效期链接就会提前失效或直接判过期。

围绕「预签名 URL 过期」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。监控和日志的时间要对上,时区不一致会多绕很大一圈。

临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。

处理上按这个顺序:先对一遍生成端和对象存储的 UTC 时间;有效期按业务给 300 到 900 秒 不要给一天;前端别在页面加载时批量生成 用到再取;确认签名没用临时凭证 临时凭证过期会另报错。

确认没问题再收工,新生成的链接在有效期内返回 200,超过设定秒数后稳定返回 403。

作者 9823189