图片文件base64入库?试试对象存储吧!OSS、BLOB、S3;对象存储最佳实践
·
☁ 对象存储最佳实践
这两天学习的心得
1 核心概念速查
| 术语 | 一句话解释 |
|---|---|
| Bucket | 存储桶,最顶层的容器,类似硬盘分区 |
| Object / Key | 存储的文件,用路径字符串(Key)唯一标识 |
| AK / SK | 访问密钥对,相当于账号+密码,绝不能泄露 |
| 预签名 URL | 后端用 SK 签名生成的带时限临时访问链接 |
| SAS Token | Azure 叫法,和预签名 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 S3 | Presigned URL | X-Amz-Expires(秒) |
| Azure Blob | SAS Token | se(过期时间戳)+ sig |
| 阿里云 OSS | 签名 URL | Expires(Unix 时间戳) |
| Google GCS | Signed URL | X-Goog-Expires(秒) |
工作流程
- 客户端向业务后端请求授权
- 后端用 SK 签名,生成带时限的 URL 返回给客户端
- 客户端拿到 URL 直接与 OSS 通信(上传或下载)
- 后端不再转发文件,省带宽、省服务器资源
常见坑
⚠️ 时钟偏差:服务器和 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配置了精确域名 -
ETag在Expose-Headers中暴露 - 各场景的 TTL 按最短够用值设置
- 高敏文件走代理传,普通文件走直传
- 公开静态资源走 CDN,不用预签名 URL
- 文件名包含 hash 或版本,避免 CDN 缓存问题
- 上传完成后有服务端校验(类型、大小、病毒扫描)
✅ 记住一句话:AK/SK 不落地,Key 进库,URL 动态生成,公开走 CDN,私有用签名,TTL 越短越好。
更多推荐


所有评论(0)