预签名 URL(Presigned URL) 是对象存储服务给出的一条“已经替你签好名”的临时地址:持有它的人,在有效期内可以对某个文件执行某个特定操作,比如上传或下载,而完全不需要拥有任何密钥。
简单说,就像小区物业给访客开了一张电子通行条,写明“只能进3号楼2单元502、只能往里搬东西、两小时内有效”,末尾盖上物业认可的电子章。访客拿这张条子刷闸机就能进,全程不知道门禁密码。保安不认人,只验章。
原理也差不多。对象存储里每个文件(对象)都有一个路径(key),云厂商给账号发一对密钥(Access Key / Secret Key)。服务端用这对密钥,把“桶名 + 对象路径 + 动作 + 过期时间 + 若干可选约束”拼成字符串,再做一次哈希运算(HMAC 之类)得到签名,然后把这些参数一起拼进 URL。浏览器拿着这条 URL 直接发起 PUT 请求上传文件;存储端收到后用自己的密钥重算一遍签名,对得上就放行。
一个容易忽略的细节:签名是纯本地计算,不需要先向存储服务发请求。所以后端能在一瞬间批量签发几十条 URL,几乎零成本。
| 方案 | 客户端拿到什么 | 有效期 | 粒度 | 泄露后果 |
|---|---|---|---|---|
| 预签名 URL | 一条带签名的地址 | 分钟级到小时级 | 绑定单个对象、单个动作 | 有效期内该对象可被读写 |
| 临时凭证(STS) | 一套受限的临时密钥 | 通常更长 | 按权限策略,范围较大 | 客户端可自行签发一批 URL |
| 公开读桶 | 什么都不用 | 永久 | 整个桶或某个前缀 | 全世界都能读 |
| 服务端中转 | 你后端的上传接口 | — | 由你写的逻辑决定 | 全部文件流量压在你的服务器上 |
区别的核心在于签名的粒度,以及谁持有凭证。临时凭证是把一把小钥匙交给客户端,让它自己签;预签名 URL 是把钥匙留在服务端,只递出一张签好的条子。前者客户端要跑 SDK、能做更多事,后者客户端可以只是一个 <input type="file">。
对从业者来说,它的意义很直接:前端代码是公开的,任何写进 JavaScript 的密钥都等于公开。想上传大文件,既不能把密钥塞进浏览器,又不想让几百 MB 的视频穿过应用服务器,预签名 URL 就是标准答案。AI 场景里同样常见:网页端拍张照片直传,再把地址交给视觉模型;或者给训练平台一条临时地址,让它自己去拉模型权重。
几个必须注意的点:条子一旦发出就收不回来(除非改密钥或删对象),所以有效期要短、权限要最小,最好只允许写某个固定路径;URL 会出现在浏览器历史、代理日志和 Referer 里,别往上挂敏感信息;参与签名的 Content-Type、文件大小等字段,客户端发请求时必须严格一致,否则验签直接失败;浏览器直传还得在桶上配好跨域(CORS)规则;分片上传要给每一片单独签。各家云厂商的具体参数和签名算法并不相同,细节以官方文档为准。
