Cloudflare R2签名不匹配求助:putObject失败但listBuckets正常
Cloudflare R2 签名不匹配问题解决
执行以下代码时返回签名不匹配错误:
await s3.getSignedUrlPromise('putObject', { Bucket: 'aya-app', Key: 'dog.png', Expires: 3600 })
错误信息:
return (<Code>SignatureDoesNotMatch</Code> )The request signature we calculated does not match the signature you provided. Check your secret access key and signing method.
但调用listBuckets接口可以正常响应:
await s3.getSignedUrlPromise('listBuckets', {})
返回结果:
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <Name>aya-app</Name> <IsTruncated>false</IsTruncated> <MaxKeys>1000</MaxKeys> <KeyCount>0</KeyCount> </ListBucketResult>
已排查内容:
- Access Key ID 正确
- Secret Access Key 正确
- 尝试过v2、v3、v4三种签名版本
完整代码如下:
import S3 from 'aws-sdk/clients/s3.js'; const s3 = new S3({ endpoint: `https://xxxxxxxxxx.r2.cloudflarestorage.com/aya-app`, accessKeyId: "xxxxxxx", secretAccessKey: "xxxxxxx", signatureVersion: 'v4', region: 'auto', version: '2006-03-01', }); async function testR2() { let listBuckets = await s3.getSignedUrlPromise('listBuckets', {}) let putObject = await s3.getSignedUrlPromise('putObject', { Bucket: 'aya-app', Key: 'dog.png', Expires: 3600 }) console.log("listBuckets", listBuckets, "putObject", putObject) } await testR2()
问题根源
S3客户端初始化时,endpoint错误附加了bucket名称/aya-app。Cloudflare R2的标准endpoint格式应为https://<你的账户ID>.r2.cloudflarestorage.com,不需要包含bucket路径。调用putObject时,同时在endpoint和参数中指定bucket,会导致签名计算的资源路径与R2预期不符,触发签名验证失败。而listBuckets接口无需指定bucket,因此不受影响。
修复方法
修改S3客户端的endpoint配置,移除末尾的/aya-app:
const s3 = new S3({ endpoint: `https://xxxxxxxxxx.r2.cloudflarestorage.com`, // 移除/aya-app accessKeyId: "xxxxxxx", secretAccessKey: "xxxxxxx", signatureVersion: 'v4', region: 'auto', version: '2006-03-01', });
保持putObject调用中的Bucket: 'aya-app'参数不变,该参数用于指定目标存储桶。
修改后重新测试,即可正常生成putObject的预签名URL。
内容的提问来源于stack exchange,提问作者Pedro Braude
相关产品推荐
相关产品推荐

