七牛云文件上传返回403错误,如何排查和解决?

Designer°子璇 阅读 189

在用七牛云的表单上传功能时,前端提交后总是返回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表单参数漏了什么?或者跨域配置哪里没配对?

我来解答 赞 13 收藏
二维码
手机扫码查看
2 条解答
端木小敏
先检查一下 token 生成逻辑,403 加上 "Invalid signature" 这个报错,大概率是上传凭证(token)有问题,而不是网络或权限配置问题。

七牛的上传 token 是由 accessKey、secretKey、bucket、key(可选)、deadline 等参数拼接后 HMAC-SHA1 签名再 Base64 编码生成的,如果其中任何一步出错,比如:
- 用了错误的 bucket 名称(注意大小写和连字符)
- deadline 时间戳单位搞错了(必须是秒级,不是毫秒)
- 签名时用了错误的待签名字符串格式(正确格式是::,如果 key 不指定的话)

就容易导致服务端校验失败,返回 403。

另外,form 表单里除了 token 和 file 字段,如果指定了 key(文件名),还必须显式传 key 字段,比如:

<input type="text" name="key" value="your-file-name.jpg" hidden>


如果后端生成 token 时用了 key,但前端没传,或者传的 key 和 token 里的不一致,也会报 403。

建议你用后端打印一下生成 token 用到的参数(尤其是 bucket 和 key),再和前端 form 提交的参数比对一下,最好在浏览器 Network 面板里看下 form 提交时实际发送的 payload 是什么。

还有个小坑:七牛上传接口默认只支持 POST,但如果你用了自定义域名做上传域名,记得确认那个域名绑定了正确的 bucket,并且在七牛控制台里没启用“私有空间”权限限制(私有空间需要 token 带 returnUrlreturnBody 参数才能正常返回结果)。

如果以上都确认没问题,可以临时用 curl 手动模拟一次上传,把 token 和文件用命令行传过去,这样能排除前端表单构造的问题。比如:

curl -F token=your_token_here -F file=@./test.jpg https://upload.qiniup.com


如果 curl 能成功,说明问题在前端;如果 curl 也 403,那就是 token 生成逻辑的问题,回头重点检查签名部分代码。
点赞 3
2026-02-27 16:05
Top丶青青
403 Forbidden 和 "Invalid signature" 基本可以确定是签名问题。你已经确认 AK/SK 有效,那可能是上传凭证生成时的 Policy 配置或者签名算法有问题。

先检查后端生成上传凭证的部分。Policy 的 scope 格式要对,时间范围也要设置合理。代码放这了,PHP 版本的示例:

// PHP 示例
use QiniuAuth;

$accessKey = '你的AK';
$secretKey = '你的SK';
$bucket = '你的存储空间名';

// 创建上传 token
function uptoken($bucket) {
global $accessKey, $secretKey;
$auth = new Auth($accessKey, $secretKey);
$putPolicy = [
'scope' => $bucket,
'deadline' => time() + 3600 // 有效期1小时
];
$token = $auth->uploadToken($bucket, null, 3600, $putPolicy);
return $token;
}

echo uptoken($bucket);


前端部分没啥大问题,但建议把 hidden 改成 type="hidden",这样更标准:

<form action="https://upload.qiniup.com" method="post" enctype="multipart/form-data">
<input type="hidden" name="token" value="后端生成的token">
<input type="file" name="file">
<button>上传</button>
</form>


最后再确认下:
1. 存储空间名是否正确
2. 时间戳是否准确(服务器时间和本地时间不能差太多)
3. 如果用的是自定义域名,CNAME 配置有没有生效

还是不行的话,直接抓个包看看请求里的 Authorization 字段对不对。
点赞 7
2026-02-01 23:10