服务端签名直传是唯一安全可行的路径,因使用临时凭证避免泄露长期密钥;需三步:配置oss(建bucket并设cors)、服务端调sts获取临时凭证并生成带policy的签名、web端用html表单提交。

直接用服务端签名直传,别在前端硬塞 AccessKeyId 和 AccessKeySecret —— 这是唯一安全可行的路径。其他方式要么泄露密钥,要么绕远路拖慢上传,没有折中。
为什么不能用 Browser.js SDK 直传
因为它的签名逻辑必须把 AccessKeyId 和 AccessKeySecret 暴露在前端 JS 里。哪怕加混淆、加动态拼接,只要运行在浏览器,就等于公开广播。实际抓包或反编译几秒就能还原出完整凭证。
- 一旦泄露,攻击者可任意读写你整个 Bucket,甚至调用 STS 接口生成更长期权限
- 阿里云控制台明确标红警告:“不推荐在前端使用永久 AK/SK”
- 即使加了 Referer 白名单或 IP 限制,也挡不住已拿到凭证的恶意请求
PostObject 签名必须带 Policy 且严格校验条件
PostObject 是 Web 表单直传的核心接口,它不接受 URL 签名,只认 base64 编码的 policy 和对应 signature。Policy 不是可选字段,而是强制校验上传行为边界的策略文档。
-
policy必须包含expiration(ISO8601 格式时间戳,不是秒数)和conditions数组 - 常见误写:
['starts-with', '$key', 'uploads/']漏掉末尾斜杠,导致上传到uploads123.jpg也被放行 - 必须校验文件大小:
['content-length-range', 1, 20971520](0–20MB),否则可能被用于 DoS 攻击 - 不要在
conditions里写死$success_action_redirect,前端跳转不可控,应由 OSS 回调(callback)或后端轮询处理结果
PHP 生成签名时要注意的三个硬坑
很多 PHP 示例代码直接抄 Node.js 版本,但 PHP 的 hash_hmac 默认输出二进制,而 OSS 要求的是 Base64 编码后的字符串;同时时间格式、换行符、JSON 编码细节稍错一点,签名就失效。
- Policy 字符串必须用
json_encode($policy, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),否则中文路径或特殊字符会导致签名不匹配 - 计算 signature 前,Policy 必须先做
base64_encode(),再用hash_hmac('sha1', $policyBase64, $accessKeySecret, true),最后再base64_encode()—— 少一层 encode 就 403 - 服务端返回给前端的
host必须是https://<bucket>.<endpoint></endpoint></bucket>(比如https://my-bucket.oss-cn-hangzhou.aliyuncs.com),不能是控制台看到的“外网访问域名”,也不能漏掉https://
前端表单提交必须用 multipart/form-data 且字段顺序固定
OSS 对表单字段顺序有隐式要求:必须把 key、policy、signature、OSSAccessKeyId、success_action_status 等放在文件字段 file 之前。顺序错乱会导致 400 错误,但错误信息里不提示具体哪错。
- HTML 表单
<input type="hidden">的 name 必须严格匹配文档:key、policy、signature、OSSAccessKeyId、success_action_status、callback(如启用) -
success_action_status建议设为201,这样上传成功后响应体是 XML,前端可直接解析<key></key>字段获取最终路径 - 不要用
fetch或XMLHttpRequest模拟表单提交 —— 它们无法构造真正的multipart/form-data边界,必须用原生<form enctype="multipart/form-data"></form>提交或 FormData +submit()
最易被忽略的是:CORS 配置必须允许 POST 方法、Content-Type 头、以及你前端实际使用的 Origin(比如 https://your-app.com),缺一不可;而很多人只配了 *,却忘了 Access-Control-Allow-Credentials: true 和 credentials 选项冲突,导致签名请求被浏览器拦截。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











