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
相关产品推荐
相关产品推荐

