我在 eu-west-2 有一个 EC2 实例。 我使用 python boto3 生成一个预签名 URL,我将其返回到 Web 浏览器以启用对文件的临时访问,以便可以显示它们。
我在多个区域设置了复制的 S3 存储桶,以及一个多区域访问点。
我用来生成预签名 URL 的代码如下:
s3Config = Config(
signature_version = 'v4'
)
s3Client_MultiRegion = boto3.client(
's3',
aws_access_key_id = appConfig.S3_ACCESS_KEY,
aws_secret_access_key = appConfig.S3_SECRET_KEY,
config = s3Config
)
protectedFileUrl = s3Client_MultiRegion.generate_presigned_url(
HttpMethod='GET',
ClientMethod="get_object",
Params={
'Bucket': appConfig.AMAZON_S3_BUCKET_MULTIREGIONACCESSPOINT_ARN,
'Key':folderPath
},
ExpiresIn=60
)
当我通过 eu-west-2 外部的 VPN 位置(例如 ap-southeast-1)从 Web 浏览器发出请求时,出现以下错误:
Error parsing the X-Amz-Credential parameter; the region 'us-east-1' is wrong; expecting 'ap-southeast-1'
如果没有指定区域,我假设它默认使用 us-east-1,但我的理解是预签名 URL 应该与位置无关,并且接入点应该路由请求。
如果确实需要指定区域,那么考虑到代码是在 Web 服务器上执行的,我该如何正确执行此操作?
如果不是,我在这里做错了什么?
顺便说一句,我在 cloudfront 发行版后面设置了公共文件,该发行版使用 lambda@edge 函数来修改标头以添加 Sig4 标头。 我假设这对于受保护的文件来说不是必需的,因为预签名 URL 无论如何都应该包含 Sig4 标头。
谢谢你。
您面临的问题是由于签署预签名 URL 时使用的区域与路由请求的区域不匹配所致。即使您使用的是 S3 多区域接入点,预签名 URL 仍然需要包含有效的区域特定签名。
创建预签名 URL 时,它会包含一个区域作为签名的一部分。如果请求最终到达不同的区域(例如在为 us-east-1 签署 URL 时路由到 ap-southeast-1 的示例中),则签名将被拒绝。
您可以使用 Lambda@edge 向标头添加一些属性以进行多区域卸载,或者您可以将region_name 添加到boto3.client s3 配置region_name='eu-west-2',这将起作用好吧,如果您的客户端和服务器通常位于同一区域,或者您可以创建一个函数来根据客户端位置动态处理region_name
def get_region_based_on_client():
...
return 'ap-southeast-1'
s3_config = Config(
signature_version='v4',
region_name=get_region_based_on_client()
)