七牛云文件上传返回403错误,如何排查和解决?
在用七牛云的表单上传功能时,前端提交后总是返回403 Forbidden错误。已经确认AK/SK有效,域名白名单也添加了测试环境IP,但问题依旧。
代码是按照官方文档写的,表单结构如下:
<form action="https://upload.qiniup.com" method="post" enctype="multipart/form-data">
<input type="text" name="token" value="生成的上传凭证" hidden>
<input type="file" name="file">
<button>上传</button>
</form>
控制台报错显示:”XMLHttpRequest cannot load. Invalid signature”,但后端生成的上传凭证是实时获取的。有没有可能是form表单参数漏了什么?或者跨域配置哪里没配对?
七牛的上传 token 是由 accessKey、secretKey、bucket、key(可选)、deadline 等参数拼接后 HMAC-SHA1 签名再 Base64 编码生成的,如果其中任何一步出错,比如:
- 用了错误的 bucket 名称(注意大小写和连字符)
- deadline 时间戳单位搞错了(必须是秒级,不是毫秒)
- 签名时用了错误的待签名字符串格式(正确格式是:
: 或,如果 key 不指定的话)就容易导致服务端校验失败,返回 403。
另外,form 表单里除了 token 和 file 字段,如果指定了 key(文件名),还必须显式传
key字段,比如:如果后端生成 token 时用了 key,但前端没传,或者传的 key 和 token 里的不一致,也会报 403。
建议你用后端打印一下生成 token 用到的参数(尤其是 bucket 和 key),再和前端 form 提交的参数比对一下,最好在浏览器 Network 面板里看下 form 提交时实际发送的 payload 是什么。
还有个小坑:七牛上传接口默认只支持 POST,但如果你用了自定义域名做上传域名,记得确认那个域名绑定了正确的 bucket,并且在七牛控制台里没启用“私有空间”权限限制(私有空间需要 token 带
returnUrl或returnBody参数才能正常返回结果)。如果以上都确认没问题,可以临时用 curl 手动模拟一次上传,把 token 和文件用命令行传过去,这样能排除前端表单构造的问题。比如:
如果 curl 能成功,说明问题在前端;如果 curl 也 403,那就是 token 生成逻辑的问题,回头重点检查签名部分代码。
先检查后端生成上传凭证的部分。Policy 的 scope 格式要对,时间范围也要设置合理。代码放这了,PHP 版本的示例:
前端部分没啥大问题,但建议把 hidden 改成 type="hidden",这样更标准:
最后再确认下:
1. 存储空间名是否正确
2. 时间戳是否准确(服务器时间和本地时间不能差太多)
3. 如果用的是自定义域名,CNAME 配置有没有生效
还是不行的话,直接抓个包看看请求里的 Authorization 字段对不对。