使用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出现签名不匹配的问题,可尝试以下修复点:
- 修正区域参数
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"}, ), )
移除重复的URL编码
boto3的generate_presigned_url会自动处理Key的URL编码,代码中导入的quote如果被用于手动编码Key,会导致签名计算的Key值与实际请求不一致,需移除不必要的编码操作。规范curl测试请求
测试时确保请求完全匹配预签名要求:
- 不添加额外请求头(预签名时指定的除外)
- 使用PUT方法,无请求体时需明确传入空内容:
curl -X PUT "生成的预签名URL" -d ""
- 验证权限配置
确认你的Access Key拥有目标存储桶的write权限,虽然签名错误通常与权限无关,但权限不足可能引发混淆性错误。
内容的提问来源于stack exchange,提问作者Deepak Suthar
相关产品推荐
相关产品推荐

