【问题标题】:ImageField with django-storages leads to: "Error parsing the X-Amz-Credential parameter; the region 'us-east-1' is wrong; expecting 'us-west-1'"带有 django-storages 的 ImageField 导致:“解析 X-Amz-Credential 参数时出错;区域 'us-east-1' 错误;期待 'us-west-1'”
【发布时间】:2022-02-22 01:34:08
【问题描述】:

我正在尝试将ImageField 添加到名为LucyGuide 的模型中,这将使用django-storages 将用户上传的图像保存到S3。这是(简化的)模型:

class LucyGuide(TimeStampedModel):
    headshot = models.ImageField(upload_to='uploads/', null=True)
    bio = models.TextField(blank=True)

我已将以下内容添加到我的settings.py

# Use Boto3 backend to interact with Amazon's S3
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

# Amazon S3 credentials (for django-storages)
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID', default='')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY', default='')

AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME', default='')
AWS_S3_REGION_NAME = os.getenv('AWS_S3_REGION_NAME')
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}
# Use v4 of the signing protocol (recommended for all new projects)
AWS_S3_SIGNATURE_VERSION = 's3v4'

.env 文件中读取实际密钥(使用类似于django-decouple 的机制)。

为了试试这个,我在 Django 的管理 UI 中为 LucyGuide 上传了一张随机图片:

在 shell 中,我可以访问指南的 headshot 字段的 url 属性,这确实是指向 AWS 存储桶的链接:

In [6]: guide = LucyGuide.objects.filter(bio__startswith="Kristen").first()

In [7]: guide
Out[7]: <LucyGuide: Kristen Hoover>

In [8]: guide.headshot
Out[8]: <ImageFieldFile: uploads/320px-Waaah.jpg>

In [9]: guide.headshot.url
Out[9]: 'https://lucy-prod.s3.amazonaws.com/uploads/320px-Waaah.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIMC2A%2F20180327%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180327T200248Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=ae75dbdd75d13020113c12ef2d655e3'

(我已删除部分 URL)。问题是当我尝试在浏览器中访问此 URL 时,我收到“此 XML 文件似乎没有与之关联的任何样式信息”错误:

<Error>
<Code>AuthorizationQueryParametersError</Code>
<Message>
Error parsing the X-Amz-Credential parameter; the region 'us-east-1' is wrong; expecting 'us-west-1'
</Message>
<Region>us-west-1</Region>
<RequestId>1E053D94011E400F</RequestId>
<HostId>
jbkRHVj2y6ygppTsAo2+uOXgby0ok0mbsFsRogKqbu9jPMb+9eGe24nJv441vip3WpmwpFqlsYg=
</HostId>
</Error>

我已经尝试通过添加AWS_S3_REGION_NAME 设置来解决这个问题(参见http://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html)。错误消息指示的区域us-west-1 似乎是正确的,因为存储桶设置在“美国西部(加利福尼亚北部)”:

总而言之,尽管设置了正确的AWS_S3_REGION_NAME,但我不明白为什么会发生此错误。我该如何解决这个错误?

更新

如果我检查存储桶中的对象,我发现它有一个“链接”,它比headshot 字段的url 属性生成的链接简单得多:

我正在考虑将此处显示的“基本 URL”硬编码到我正在尝试构建的用于检索图像 URL 的 API 端点中,但这似乎不是一个优雅的解决方案。有更好的想法吗?

【问题讨论】:

    标签: python django amazon-web-services amazon-s3


    【解决方案1】:

    您可以简单地使用 AWS_S3_REGION_NAME = ''us-east-2' # 将 us-east-2 替换为您的区域,而不是关闭查询字符串。更安全。

    【讨论】:

      【解决方案2】:

      通过阅读(并在其中设置断点)django-storages 源代码,我能够通过添加设置来解决问题

      AWS_QUERYSTRING_AUTH = False
      

      将其从默认值True 更改。现在url 属性会生成一个没有身份验证查询字符串的 URL:

      In [2]: guide = LucyGuide.objects.filter(bio__startswith='Darrell').first()
      
      In [3]: guide.headshot
      Out[3]: <ImageFieldFile: uploads/Waaah.jpg>
      
      In [4]: guide.headshot.url
      Out[4]: 'https://lucy-prod.s3.amazonaws.com/uploads/Waaah.jpg'
      

      【讨论】:

      • 我可能错了,但是你在桶上开了一个洞。查询字符串身份验证的存在是有充分理由的,它在特定时间段内限制对图像的访问。如果没有这个,任何具有公共阅读能力的人都可以从您的上传文件夹中查看和下载所有其他图像。如果它的意图是好的,但不确定它是。
      【解决方案3】:

      您需要将变量 AWS_S3_REGION_NAME 添加到 settings.py。 您的 env 文件中可能缺少它 另见:https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html

      【讨论】:

        猜你喜欢
        • 2018-03-26
        • 2018-05-19
        • 1970-01-01
        • 2019-03-21
        • 1970-01-01
        • 2020-11-10
        • 2020-01-30
        • 2021-12-05
        • 2023-03-22
        相关资源
        最近更新 更多