You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django无法访问S3存储桶,仅开放公共权限才可访问的问题

问题描述

我将AWS S3存储桶用于Django的静态文件与媒体文件存储,已在settings.py中配置IAM用户凭证,可通过python manage.py collectstatic将文件上传至存储桶。但仅当设置如下完全开放的存储桶策略时,才能访问桶内文件:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucketname/*"
        }
    ]
}

若设置仅授权指定IAM用户的存储桶策略(如下),则会出现“访问被禁止”错误:

{
    "Version": "2012-10-17",
    "Id": "ExamplePolicy01",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::499213337707:user/bucketusername"
            },
            "Action": [
                "s3:GetObject",
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::bucketname/*"
            ]
        }
    ]
}

已确认IAM访问密钥与密钥密码正确,settings.py相关配置如下:

#S3 Bucket config
AWS_ACCESS_KEY_ID = 'Key ID here'

AWS_SECRET_ACCESS_KEY = 'secret key here'
AWS_STORAGE_BUCKET_NAME = 'bucketname'
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'


#AWS S3 Settings
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

AWS_LOCATION = 'static'
STATICfILES_DIRs = [
    str(BASE_DIR.joinpath('static')),
]
STATIC_ROOT = BASE_DIR / "static"
STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{AWS_LOCATION}/'


STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    # other finders..
    'compressor.finders.CompressorFinder',
)

MEDIA_URL = '//%s.s3.amazonaws.com/media/' % AWS_STORAGE_BUCKET_NAME
MEDIA_ROOT = MEDIA_URL
AWS_QUERYSTRING_AUTH = False # needed for ckeditor with S3
AWS_DEFAULT_ACL = 'public-read'

请问如何配置才能仅让持有合法凭证的请求访问存储桶?

解决方案

1. 修正存储桶策略的资源范围

当前策略中Resource仅包含桶内对象(arn:aws:s3:::bucketname/*),但ListBucket和GetBucketLocation操作需要授权桶本身(arn:aws:s3:::bucketname)。调整后的策略如下:

{
    "Version": "2012-10-17",
    "Id": "ExamplePolicy01",
    "Statement": [
        {
            "Sid": "ObjectLevelPerms",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::499213337707:user/bucketusername"
            },
            "Action": [
                "s3:GetObject",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::bucketname/*"
        },
        {
            "Sid": "BucketLevelPerms",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::499213337707:user/bucketusername"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::bucketname"
        }
    ]
}

2. 开启URL签名验证

你当前设置AWS_QUERYSTRING_AUTH = False,会生成不带签名的公开URL,浏览器访问时无IAM凭证导致被拒绝。要实现仅合法凭证访问,需开启签名:

AWS_QUERYSTRING_AUTH = True

开启后Django生成的URL会包含临时签名,只有持有有效IAM密钥的请求能通过验证访问资源。

3. 修复ACL配置冲突

settings.py中同时设置了AWS_DEFAULT_ACL = None和AWS_DEFAULT_ACL = 'public-read',最终生效的public-read会让上传文件自动设为公开可读,与需求冲突。保留AWS_DEFAULT_ACL = None即可:

# 移除或注释掉这一行
# AWS_DEFAULT_ACL = 'public-read'
AWS_DEFAULT_ACL = None

4. 确保IAM用户权限充足

除存储桶策略外,需给IAM用户附加对应权限策略,确保拥有必要的S3操作权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:GetBucketLocation",
                "s3:ListBucket",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::bucketname",
                "arn:aws:s3:::bucketname/*"
            ]
        }
    ]
}

内容的提问来源于stack exchange,提问作者Finn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:07:02