django - 如何让 Django 在 AWS S3 上将某些文件设为公开,将媒体文件设为私有(private)(无 403 错误)?

标签 django amazon-s3 boto3 http-status-code-403 python-django-storages

我在 Django 应用程序中使用 boto3django-storages 来提供来自 AWS S3 的文件。我希望我的静态文件是公开的,但其他文件是私有(private)的。我已经有点工作但不完全。我的静态文件就像私有(private)文件一样使用预签名 key 。在我的模板文件中,当我使用时:

<img src="{% static 'images/3d-house-nav-gray.png' %}">

而不是我想要的

<img src="https://mybucket.s3.amazonaws.com/static/images/3d-house-nav-gray.png">

我懂了

<img id="home-img" src="https://mybucket.s3.amazonaws.com/static/images/3d-house-nav-gray.png?AWSAccessKeyId=AKIA1234564LQ7X4EGHK&amp;Signature=123456gIBTFlTQKCexLo3UJmoPs%3D&amp;Expires=1621693552">

当模板作为 HTTPResponse 的一部分从服务器呈现时,这实际上有效,但当像这样的图像只是作为 .css 文件的一部分包含时,则不起作用。在这种情况下我会得到:

Failed to load resource: the server responded with a status of 403 (Forbidden)

(我发现,如果我复制并粘贴有问题的图像链接,并将 & 替换为 &,那么我就可以访问,这又是一个谜。)

以下是我配置 AWS 的方式:

AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
AWS_STORAGE_BUCKET_NAME = 'mybucket'
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}
AWS_DEFAULT_ACL = None
AWS_LOCATION = 'static'
STATICFILES_STORAGE = 'myapp.storage_backends.StaticStorage'
DEFAULT_FILE_STORAGE = 'myapp.storage_backends.MediaStorage'
AWS_S3_URL = 'https://%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
STATIC_DIRECTORY = '/static/'
MEDIA_DIRECTORY = '/media/'
STATIC_URL = AWS_S3_URL + STATIC_DIRECTORY
MEDIA_URL = AWS_S3_URL + MEDIA_DIRECTORY

其中 myapp.storage_backends.py 包含:

from storages.backends.s3boto3 import S3Boto3Storage

class MediaStorage(S3Boto3Storage):
    location = 'media'
    file_overwrite = False

class StaticStorage(S3Boto3Storage):
    location = 'static'
    file_overwrite = True

在 AWS S3 上,我的存储桶策略设置如下:

{
    "Version": "2012-10-17",
    "Id": "Policy1621539673651",
    "Statement": [
        {
            "Sid": "Stmt1621539665305",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::063896663644:user/mylogin"
            },
            "Action": [
                "s3:GetObject",
                "s3:GetObjectAcl",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::mybucket/*"
        },
        {
            "Sid": "Stmt1621539600741",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::mybucket/static/*"
        }
    ]
}

如何修复此问题以使某些文件(如 static/中的所有文件)未签名且公开,而其他文件已签名且私有(private)?

最佳答案

如果你看一下 django-storages 的源代码,您将看到一个名为 S3StaticStorage未记录类:

class S3StaticStorage(S3Boto3Storage):
    """Querystring auth must be disabled so that url() returns a consistent output."""
    querystring_auth = False

从此子类化应该可以解决您的问题。

关于django - 如何让 Django 在 AWS S3 上将某些文件设为公开,将媒体文件设为私有(private)(无 403 错误)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67650507/

相关文章:

django - 如何让 Gunicorn 使用 Python 3 而不是 Python 2(502 Bad Gateway)

hadoop - 使用 s3 的 spark 加载 json 时 FS 错误

hadoop - 将 HDFS 从本地磁盘替换为 s3 出现错误 (org.apache.hadoop.service.AbstractService)

amazon-web-services - 如何在 "s3 sync"中包含空文件夹?

database - 如何使用boto3在dynamodb中查询大于排序键

boto3,Windows 上的凭据文件在哪里?

python - 如何允许来自 Axios 的 CORS 在 Django 后端获取请求?

Django内置密码重置,我的网址有什么问题?

python - Django 中 "}"的来源(当前路径,entries/},与其中任何一个都不匹配。)

python - S3 预签名 URL 在存储桶创建后 90 分钟有效