You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用boto3生成Backblaze B2预签名PUT URL遇SignatureDoesNotMatch错误

问题:使用boto3生成Backblaze B2预签名PUT URL时返回SignatureDoesNotMatch错误

我尝试用boto3为兼容S3 API的Backblaze B2生成预签名PUT URL,但哪怕是最简单的curl PUT请求都会返回SignatureDoesNotMatch错误。这个问题在没有额外请求头的情况下也会出现,所以排除浏览器或CORS问题。

环境信息

  • 存储服务商:Backblaze B2(兼容S3)
  • 区域:eu-central-003
  • 端点:https://s3.eu-central-003.backblazeb2.com
  • 签名版本:AWS4-HMAC-SHA256
  • 寻址样式:path
  • 签名方式:boto3 / botocore预签名

boto3客户端配置与URL生成代码

import boto3
from botocore.config import Config
from functools import lru_cache
from urllib.parse import quote

def create_s3_client():
    return boto3.client(
        service_name="s3",
        region_name="eu-central-003",
        endpoint_url="https://s3.eu-central-003.backblazeb2.com",
        aws_access_key_id="ACCESS_KEY",
        aws_secret_access_key="SECRET_KEY",
        config=Config(
            signature_version="s3v4",
            s3={"addressing_style": "path"},
        ),
    )

@lru_cache
def get_s3_client():
    return create_s3_client()

def generate_upload_url(key: str):
    client = get_s3_client()
    return client.generate_presigned_url(
        "put_object",
        Params={
            "Bucket": "Major-project-bucket",
            "Key": key,
        },
        ExpiresIn=600,
    )

存储桶CORS设置

{
    "bucketInfo": {},
    "bucketName": "Major-project-bucket",
    "bucketType": "allPrivate",
    "corsRules": [
        {
            "allowedHeaders": [
                "*"
            ],
            "allowedOperations": [
                "s3_put"
            ],
            "allowedOrigins": [
                "*"
            ],
            "corsRuleName": "allow-s3-uploads",
            "exposeHeaders": [
                "etag"
            ],
            "maxAgeSeconds": 3600
        },
        {
            "allowedHeaders": [
                "*"
            ],
            "allowedOperations": [
                "s3_head",
                "s3_get"
            ],
            "allowedOrigins": [
                "*"
            ],
            "corsRuleName": "allow-s3-downloads",
            "exposeHeaders": [
                "content-length",
                "etag"
            ],
            "maxAgeSeconds": 3600
        }
    ],
    "defaultRetention": {
        "mode": null
    },
    "defaultServerSideEncryption": {
        "mode": "none"
    },
    "isFileLockEnabled": false,
    "lifecycleRules": [
        {
            "daysFromHidingToDeleting": 1,
            "daysFromStartingToCancelingUnfinishedLargeFiles": null,
            "daysFromUploadingToHiding": null,
            "fileNamePrefix": ""
        }
    ],
    "options": [
        "s3"
    ],
    "replication": {
        "asReplicationDestination": null,
        "asReplicationSource": null
    },
    "revision": 6
}

解决方案

针对Backblaze B2的S3兼容API,预签名PUT URL出现签名不匹配的问题,可尝试以下修复点:

  1. 修正区域参数
    Backblaze B2的S3兼容API签名逻辑使用简化的区域标识,对于eu-central-003,需将客户端的region_name改为eu-central-0(去掉末尾三位数字后缀)。修改后的客户端创建代码:
def create_s3_client():
    return boto3.client(
        service_name="s3",
        region_name="eu-central-0",  # 修正区域标识
        endpoint_url="https://s3.eu-central-003.backblazeb2.com",
        aws_access_key_id="ACCESS_KEY",
        aws_secret_access_key="SECRET_KEY",
        config=Config(
            signature_version="s3v4",
            s3={"addressing_style": "path"},
        ),
    )
  1. 移除重复的URL编码
    boto3的generate_presigned_url会自动处理Key的URL编码,代码中导入的quote如果被用于手动编码Key,会导致签名计算的Key值与实际请求不一致,需移除不必要的编码操作。

  2. 规范curl测试请求
    测试时确保请求完全匹配预签名要求:

  • 不添加额外请求头(预签名时指定的除外)
  • 使用PUT方法,无请求体时需明确传入空内容:
curl -X PUT "生成的预签名URL" -d ""
  1. 验证权限配置
    确认你的Access Key拥有目标存储桶的write权限,虽然签名错误通常与权限无关,但权限不足可能引发混淆性错误。

内容的提问来源于stack exchange,提问作者Deepak Suthar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 11:43:13