如何让 Django 在 AWS S3 上将一些文件设为公共文件和媒体文件私有(没有 403 错误)? [英] How to get Django to make some files public and media files private on AWS S3 (no 403 errors)?

查看:23
本文介绍了如何让 Django 在 AWS S3 上将一些文件设为公共文件和媒体文件私有(没有 403 错误)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的 Django 应用程序中使用 boto3django-storages 来提供来自 AWS S3 的文件.我希望我的静态文件是公开的,但其他文件是私有的.我有点工作,但不完全.我的静态文件就好像它们是私有的一样,带有预签名的密钥.在我使用时的模板文件中:

I'm using boto3 and django-storages in my Django app to serve files from AWS S3. I'd like my static files to be public but other files to be private. I've got it kinda sorta working but not quite. My static files are being served as if they're private, with a pre-signed key. In my template file when I use:

<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 文件的一部分包含时则无效.在这种情况下,我会得到:

This actually works when the templates are rendered from the server as part of an HTTPResponse, but not when an image like this is simply included as part of, say, a .css file. In that case I'll get:

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

(我发现如果我复制并粘贴有问题的图像链接并将 &amp; 替换为 & 然后我可以访问,这是一个进一步的谜.)

(I find that if I copy and paste the problematic image link and replace the &amp; with an & then I have access, a further mystery.)

这是我配置 AWS 的方式:

Here is how I have AWS configured:

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 上,我的存储桶策略设置如下:

And on AWS S3, my bucket policy is set up like so:

{
    "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/中的所有文件)未签名和公开,但其他文件已签名和私有?

How can I fix this to make certain files (like everything in static/) unsigned and public, but other files signed and private?

推荐答案

如果你看一下 django-storages,你会看到一个未记录的类称为 S3StaticStorage:

If you take a look at the source code for django-storages, you will see an undocumented class called S3StaticStorage:

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

从这个子类化应该可以解决你的问题.

Subclassing from this should fix your problem.

这篇关于如何让 Django 在 AWS S3 上将一些文件设为公共文件和媒体文件私有(没有 403 错误)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆