我尝试使用 boto3 库为
me-central-1
区域中的 S3 存储桶生成预签名 URL,如下所示
client = boto3.client("s3", region_name="me-central-1")
return client.generate_presigned_url(
ClientMethod="put_object",
Params={"Bucket": bucket, "Key": path},
)
这会生成以下形式的 url:
https://bucket.s3.amazonaws.com/path?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={CREDENTIAL}/{DATE}/me-central-1/s3/aws4_request&X-Amz-Date={DATETIME}&X-Amz-Expires=1800&X-Amz-SignedHeaders=host&X-Amz-Signature={SIGNATURE}
但是,尝试使用此 url 会导致
IllegalLocationConstraintException
并显示以下消息:The me-central-1 location constraint is incompatible for the region specific endpoint this request was sent to.
我对发生这种情况的原因进行了一些研究,发现前往 us-east-1 以外区域的 S3 端点需要包含该区域,如下所示:
https://bucket.s3.REGION.amazonaws.com/...
。
然后我将 boto3 客户端实例更改为以下版本:
client = boto3.client("s3", region_name="me-central-1", endpoint_url="https://s3.me-central-1.amazonaws.com")
生成的 url 格式为:
https://s3.me-central-1.amazonaws.com/bucket/path?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential={CREDENTIAL}/{DATE}/me-central-1/s3/aws4_request&X-Amz-Date={DATETIME}&X-Amz-Expires=1800&X-Amz-SignedHeaders=host&X-Amz-Signature={SIGNATURE}
此 URL 似乎可以正常工作,而不会返回
IllegalLocationConstraintException
!但是,我注意到这现在是路径式请求,而不是虚拟托管式请求(如here所定义)。提供的网页还指出路径样式请求将停止,因此我将无法使用上述代码作为长期解决方案。
我尝试手动将路径样式请求更改为虚拟托管样式请求,导致出现
SignatureDoesNotMatch
错误,并显示消息:The request signature we calculated does not match the signature you provided. Check your key and signing method
。
我的问题是 - 有没有办法让 boto3 客户端返回有效的虚拟托管样式预签名 url?
import boto3
from botocore.client import Config
client = boto3.client(
"s3",
region_name="me-central-1",
endpoint_url="https://s3.me-central-1.amazonaws.com",
config=Config(s3={'addressing_style': 'virtual'})
)
return client.generate_presigned_url(
ClientMethod="put_object",
Params={"Bucket": bucket, "Key": path},
)