Django上传静态文件到Amazon S3时遭遇403 Forbidden错误求助
Django静态文件上传S3出现403 Forbidden错误的解决方法
问题背景
尝试通过boto3和django-storages模块将Django项目的静态文件上传至Amazon S3,执行python manage.py collectstatic命令时触发403 Forbidden错误,具体报错出现在HeadObject操作环节。
现有配置
settings.py中的AWS配置
AWS_ACCESS_KEY_ID = "<public-key>" AWS_SECRET_ACCESS_KEY_ID = "<private-key>" AWS_STORAGE_BUCKET_NAME = "<bucket-name>" STORAGES = { # Media files (images) management "default": { "BACKEND": "storages.backends.s3boto3.S3StaticStorage", }, # CSS and JS file management "staticfiles": { "BACKEND": "storages.backends.s3boto3.S3StaticStorage", }, } AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com' AWS_S3_FILE_OVERWRITE = False
IAM用户权限
已为IAM用户授予AmazonS3FullAccess权限策略。
S3存储桶策略
{ "Version": "2012-10-17", "Id": "Policy1706347165594", "Statement": [ { "Sid": "Stmt1706347164281", "Effect": "Allow", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::<bucket-name>/*" } ] }
完整报错信息
You have requested to collect static files at the destination location as specified in your settings. This will overwrite existing files! Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: yes Traceback (most recent call last): File "/home/gajeet/Documents/Django/Django_ultimate/dev2/manage.py", line 22, in <module> main() File "/home/gajeet/Documents/Django/Django_ultimate/dev2/manage.py", line 18, in main execute_from_command_line(sys.argv) File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/django/core/management/base.py", line 412, in run_from_argv self.execute(*args, **cmd_options) File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/django/core/management/base.py", line 458, in execute output = self.handle(*args, **options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 209, in handle collected = self.collect() ^^^^^^^^^^^^^^ File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 135, in collect handler(path, prefixed_path, storage) File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 368, in copy_file if not self.delete_file(path, prefixed_path, source_storage): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 278, in delete_file if self.storage.exists(prefixed_path): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/storages/backends/s3.py", line 514, in exists self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name) File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/botocore/client.py", line 553, in _api_call return self._make_api_call(operation_name, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/gajeet/Documents/Django/Django_ultimate/dev2/.venv/lib/python3.11/site-packages/botocore/client.py", line 1009, in _make_api_call raise error_class(parsed_response, operation_name) botocore.exceptions.ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden
解决步骤
1. 修正settings.py中的密钥配置错误
settings里的密钥配置项写错了,AWS_SECRET_ACCESS_KEY_ID应改为AWS_SECRET_ACCESS_KEY,去掉末尾的_ID:
AWS_ACCESS_KEY_ID = "<public-key>" AWS_SECRET_ACCESS_KEY = "<private-key>" # 修正此处
2. 扩展存储桶策略的资源范围
当前存储桶策略仅授权了桶内对象的权限,HeadObject操作需要对桶本身的访问权限。更新策略,添加桶级资源:
{ "Version": "2012-10-17", "Id": "Policy1706347165594", "Statement": [ { "Sid": "Stmt1706347164281", "Effect": "Allow", "Principal": "*", "Action": "s3:*", "Resource": [ "arn:aws:s3:::<bucket-name>", "arn:aws:s3:::<bucket-name>/*" ] } ] }
3. 验证IAM用户权限有效性
虽然已授予AmazonS3FullAccess,需确认该策略已正确附加到IAM用户,且访问密钥未过期或禁用。可通过AWS CLI测试:
aws s3 head-object --bucket <bucket-name> --key test-key
若返回正常则权限没问题,若仍报403需检查IAM用户的权限边界或是否存在其他拒绝策略。
4. 检查存储桶的Block Public Access设置
若存储桶开启了Block Public Access,会覆盖存储桶策略的公开权限。进入S3控制台,在对应桶的Permissions栏下查看Block Public Access,根据需求调整选项(若静态文件需要公开访问,需关闭相关阻止项)。
5. 修正STORAGES的后端配置(可选)
媒体文件应使用S3Boto3Storage而非S3StaticStorage,静态文件用S3StaticStorage是正确的,调整默认存储后端:
STORAGES = { # Media files (images) management "default": { "BACKEND": "storages.backends.s3boto3.S3Boto3Storage", # 修正此处 }, # CSS and JS file management "staticfiles": { "BACKEND": "storages.backends.s3boto3.S3StaticStorage", }, }
内容的提问来源于stack exchange,提问作者G Ajeet
相关产品推荐
相关产品推荐

