☁ 对象存储最佳实践

这两天学习的心得


1 核心概念速查

术语一句话解释
Bucket存储桶,最顶层的容器,类似硬盘分区
Object / Key存储的文件,用路径字符串(Key)唯一标识
AK / SK访问密钥对,相当于账号+密码,绝不能泄露
预签名 URL后端用 SK 签名生成的带时限临时访问链接
SAS TokenAzure 叫法,和预签名 URL 本质一样
Bucket Policy桶级别的访问策略,控制谁能做什么操作
CORS跨域配置,浏览器直传时必须正确配置
CDN内容分发网络,公开文件加速利器,省流量费
TTL预签名 URL 的有效时间,过期自动失效

在这里插入图片描述

2 URL 怎么存:只存 Key,不存完整 URL

✅ 正确做法

  • 数据库只存 Bucket + Key,例如:avatars/user_123/photo.jpg
  • 对外暴露时,按场景动态拼接或生成 URL
  • 公开文件 → 拼 CDN 域名;私有文件 → 生成预签名 URL

❌ 禁止做法

  • 不要把预签名 URL 存入数据库(带 TTL,过期即 404)
  • 不要存带域名的完整路径(换域名时历史数据全部报废)

💡 为什么? Key 是永久的,域名和签名都是会变的。Key 存一次,URL 每次动态生成,灵活且安全。


3 权限:记住这三层

优先级层级作用
第一层IAM / AK·SK账号级身份认证,控制谁能调用 API
第二层Bucket Policy桶级策略,控制路径前缀、操作类型、来源 IP
第三层Object ACL单文件覆盖,优先级最高,尽量少用

关键原则

  • Bucket 默认设为 Private,不要图省事设成 Public
  • 公开内容(头像、商品图)单独用一个 Bucket 或路径前缀
  • AK/SK 绝不出现在前端代码和 Git 仓库
  • 生产环境用实例角色(Instance Role / RAM Role),做到密钥不落地
  • CORS 的 AllowedOrigin 不要写 *,精确到业务域名

4 预签名 URL / SAS:最常用的临时授权

各厂商叫法对照

厂商叫法过期参数
AWS S3Presigned URLX-Amz-Expires(秒)
Azure BlobSAS Tokense(过期时间戳)+ sig
阿里云 OSS签名 URLExpires(Unix 时间戳)
Google GCSSigned URLX-Goog-Expires(秒)

工作流程

  1. 客户端向业务后端请求授权
  2. 后端用 SK 签名,生成带时限的 URL 返回给客户端
  3. 客户端拿到 URL 直接与 OSS 通信(上传或下载)
  4. 后端不再转发文件,省带宽、省服务器资源

常见坑

⚠️ 时钟偏差:服务器和 OSS 时间不同步会导致签名立即失效,确保 NTP 同步,TTL 留足 buffer。

⚠️ Content-Type 不一致:PUT 直传时,前端请求头的 Content-Type 必须与签名时一致,否则 403。

⚠️ URL 泄露无法撤销:预签名 URL 本质是公开的,拿到就能访问。不能依赖它做细粒度的人员权限控制。


5 TTL:有效期怎么定

场景推荐 TTL说明
用户上传(PUT)5 ~ 15 分钟越短越安全,够用即可
文件预览 / 下载15 分钟 ~ 1 小时按用户操作时长估算
邮件 / 分享链接1 ~ 7 天需配合业务层吊销机制
公开静态资源不设 TTL走 CDN 永久 URL,不用签名

💡 黄金原则:TTL 太短 = 用户体验差;TTL 太长 = 泄露风险大。按场景卡最短够用的值。


6 直传 vs 代理传:怎么选

方式优点适用场景
直传(Client → OSS)省带宽、服务器压力小头像、普通文档等低敏文件
代理传(Client → Server → OSS)可审查内容、更安全合同、医疗、高敏感文件

实践建议:两者结合使用。小文件、低敏感度 → 直传;高安全要求 → 代理传。


7 高频踩坑速查

问题等级解决方案
前端代码含 AK/SK🔴 严重立刻轮换密钥,改用后端签名或实例角色
CORS 没配 AllowedOrigin🟡 常见浏览器直传报跨域错误,精确配置来源域名
ETag 未在 Expose-Headers 里🟡 常见前端拿不到上传后的文件指纹,加上即可
公开文件用预签名 URL🟡 成本请求全部打到 OSS Origin,费用暴增,改走 CDN
数据库存完整预签名 URL🟠 设计TTL 过期即 404,改存 Key,动态生成 URL
文件名未加 hash/版本号🟡 缓存CDN 缓存旧文件,内容更新但 URL 不变不生效
Bucket 全局 Public Read🔴 严重任何人可遍历所有文件,立刻改为 Private
上传后未校验文件类型🟠 安全服务端签名前检查扩展名和 MIME 类型

8 上线前决策清单

  • 数据库存的是 Key,不是完整 URL
  • AK/SK 没有硬编码在代码或配置文件里
  • Bucket 默认 Private,公开内容单独隔离
  • CORS AllowedOrigin 配置了精确域名
  • ETagExpose-Headers 中暴露
  • 各场景的 TTL 按最短够用值设置
  • 高敏文件走代理传,普通文件走直传
  • 公开静态资源走 CDN,不用预签名 URL
  • 文件名包含 hash 或版本,避免 CDN 缓存问题
  • 上传完成后有服务端校验(类型、大小、病毒扫描)

记住一句话:AK/SK 不落地,Key 进库,URL 动态生成,公开走 CDN,私有用签名,TTL 越短越好。

更多推荐