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

Django连接AWS触发403 Forbidden错误,寻求排查方案

Django项目连接AWS S3执行collectstatic报403 Forbidden错误

问题描述

从Git克隆了一个此前可正常运行的Django项目,尝试连接AWS时执行collectstatic命令触发403错误,错误栈如下:

Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\django\core\management\__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\django\core\management\base.py", line 328, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\django\core\management\base.py", line 369, in execute
    output = self.handle(*args, **options)
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 187, in handle
    collected = self.collect()
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 113, in collect
    handler(path, prefixed_path, storage)
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 338, in copy_file
    if not self.delete_file(path, prefixed_path, source_storage):
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 248, in delete_file
    if self.storage.exists(prefixed_path):
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\storages\backends\s3boto3.py", line 469, in exists
    self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name)
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\botocore\client.py", line 401, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "C:\Users\cuens\PycharmProjects\frozen-brushlands-41873\venv\lib\site-packages\botocore\client.py", line 731, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden

项目中的AWS配置:

AWS_S3_ACCESS_KEY_ID = os.environ.get('AWS_S3_ACCESS_KEY_ID')
AWS_s3_SECRET_ACCESS_KEY = os.environ.get('AWS_S3_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')

AWS_S3_HOST = 's3.us-east-2.amazonaws.com'
AWS_S3_REGION_NAME = 'us-east-2'
AWS_S3_CUSTOM_DOMAIN = '%s.%s' % (AWS_STORAGE_BUCKET_NAME, AWS_S3_HOST)
AWS_DEFAULT_ACL = None

AWS_LOCATION = 'static'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]

STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)

PUBLIC_MEDIA_LOCATION = 'media'
MEDIA_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, PUBLIC_MEDIA_LOCATION)
DEFAULT_FILE_STORAGE = 'blog.storage_backends.MediaStorage'

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'

S3桶权限配置:

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::wickedphoto-blog/*"
        }
    ]
}

项目克隆前可正常运行,目前无法定位问题,需要排查。


排查与解决步骤

1. 修正环境变量键名大小写问题

配置中AWS_s3_SECRET_ACCESS_KEY的s3是小写,而标准环境变量键应为全大写的AWS_S3_SECRET_ACCESS_KEY,这会导致无法正确读取密钥,直接引发权限错误。修改为:

AWS_S3_SECRET_ACCESS_KEY = os.environ.get('AWS_S3_SECRET_ACCESS_KEY')

2. 补充IAM用户必要权限

当前S3桶策略仅允许公共读取GetObject,但collectstatic需要写入、列出、检查对象存在的权限。给对应IAM用户添加以下策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket",
                "s3:HeadObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::wickedphoto-blog",
                "arn:aws:s3:::wickedphoto-blog/*"
            ]
        }
    ]
}

3. 修复存储配置覆盖问题

配置中两次设置DEFAULT_FILE_STORAGE,最后一行会覆盖自定义的MediaStorage。如果原项目依赖自定义存储后端处理媒体文件,需保留第一行;否则删除重复配置,确保逻辑一致。

4. 验证桶名与区域匹配

确认AWS_STORAGE_BUCKET_NAME环境变量值为wickedphoto-blog,且桶确实创建在us-east-2区域,区域不匹配会导致签名错误触发403。

5. 直接测试凭证有效性

用AWS CLI测试凭证能否访问桶:

aws s3 ls s3://wickedphoto-blog --region us-east-2

若返回403,说明凭证本身无权限;若能列出内容,再检查Django配置是否正确读取环境变量。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:20:40