使用Boto3生成S3 put_object预签名URL时遇SignatureDoesNotMatch错误
解决S3预签名PUT URL返回
SignatureDoesNotMatch的问题 核心原因:请求参数与预签名生成时的参数不匹配
当生成PUT类型的预签名URL时,S3会把请求中关键头信息(比如Content-Type)纳入签名计算。如果实际发送PUT请求时,这些头信息和生成URL时指定的不一致,就会触发签名不匹配错误。而GET请求通常不需要这些额外头信息,所以你的GET预签名URL能正常工作。
具体解决步骤
1. 确保PUT请求携带完全匹配的Content-Type头
你的代码里已经指定了ContentType: 'application/json',所以发送PUT请求时必须在请求头里带上这个值,不能省略或写错。
- 用curl测试示例:
curl -X PUT -H "Content-Type: application/json" -d '{"key": "value"}' "你的预签名URL"
- 用Python requests库发送请求示例:
import requests presigned_url = get_put_presigned_url() data = {"key": "value"} headers = {"Content-Type": "application/json"} response = requests.put(presigned_url, json=data, headers=headers)
2. 移除不必要的HttpMethod参数(可选)
你的代码里指定了HttpMethod='PUT',但generate_presigned_url的ClientMethod是put_object时,默认的HttpMethod就是PUT,这个参数可以省略,避免不必要的冲突。修改后的代码:
def get_put_presigned_url(): s3_client = boto3.client('s3') response = s3_client.generate_presigned_url( ClientMethod='put_object', Params={ 'Bucket': "my-bucket", 'Key': "test.json", 'ContentType': 'application/json' }, ExpiresIn=3600 ) return response
3. 检查签名版本兼容性
如果你的S3桶要求使用v4签名,确保boto3客户端配置了正确的签名版本。可以在初始化客户端时指定:
s3_client = boto3.client( 's3', config=boto3.session.Config(signature_version='s3v4') )
大部分现代AWS区域默认使用v4签名,但有些旧区域可能需要显式指定。
4. 避免请求中包含未预签名的额外头信息
除了Content-Type,如果生成预签名URL时没有指定其他头(比如Content-Length、x-amz-*系列头),实际请求时也不能添加这些头,否则会导致签名不匹配。
验证方法
生成预签名URL后,先通过curl工具测试,确保请求头完全匹配,排除客户端代码的干扰。如果curl能成功,再排查自己的上传代码是否有头信息遗漏或错误。
内容的提问来源于stack exchange,提问作者Guillaume Monzerol
相关产品推荐
相关产品推荐

