DigitalOcean Spaces对接Django/Wagtail:上传SSL验证错误排查
Django/Wagtail 部署在DigitalOcean AppPlatform时,Spaces媒体存储URL重复桶名导致SSL验证失败
上传图片时持续失败,报错信息如下:
[2024-04-17 21:40:33] botocore.exceptions.SSLError: SSL validation failed for https://mybucket.mybucket.nyc3.digitaloceanspaces.com/original_images/Screenshot_2024-04-01_at_2.10.53PM.png hostname 'mybucket.mybucket.nyc3.digitaloceanspaces.com' doesn't match either of '*.nyc3.digitaloceanspaces.com', 'nyc3.digitaloceanspaces.com'
可见URL中存储桶名称重复两次(mybucket.mybucket),但无法定位原因。
相关配置信息
Django production.py 配置
AWS_ACCESS_KEY_ID = os.getenv('SPACES_ACCESS_KEY_ID') AWS_SECRET_ACCESS_KEY = os.getenv('SPACES_SECRET_KEY') AWS_STORAGE_BUCKET_NAME = os.getenv('SPACES_BUCKET_NAME') AWS_DEFAULT_ACL = 'public-read' AWS_S3_ENDPOINT_URL = os.getenv('SPACES_ENDPOINT_URL') AWS_S3_REGION_NAME = os.getenv('SPACES_REGION') AWS_S3_OBJECT_PARAMETERS = { 'CacheControl': 'max-age=86400', } AWS_S3_SIGNATURE_VERSION = 's3v4' AWS_S3_ADDRESSING_STYLE = 'virtual' AWS_LOCATION = os.getenv('SPACES_FOLDER') DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' MEDIA_URL = '%s/' % (AWS_S3_ENDPOINT_URL)
DigitalOcean 环境变量配置
SPACES_ACCESS_KEY_ID=XXXXXX SPACES_SECRET_KEY=XXXXXX SPACES_BUCKET_NAME=mybucket SPACES_ENDPOINT_URL=https://mybucket.nyc3.digitaloceanspaces.com SPACES_REGION=nyc3 SPACES_FOLDER=static
已安装依赖
- boto3 (v1.34.84)
- botocore (v1.34.84)
- django-storages (v1.14.2)
注:
storages已加入INSTALLED_APPS
自定义存储类 storages_backends.py
from django.conf import settings from storages.backends.s3boto3 import S3Boto3Storage class StaticStorage(S3Boto3Storage): location = 'static' class MediaStorage(S3Boto3Storage): location = ''
额外尝试
将SPACES_ENDPOINT_URL改为不带桶名的https://nyc3.digitaloceanspaces.com时,会触发SignatureDoesNotMatch错误。
问题原因与解决方案
核心原因
你启用了虚拟主机寻址模式(AWS_S3_ADDRESSING_STYLE = 'virtual'),但SPACES_ENDPOINT_URL中包含了桶名,同时MEDIA_URL的拼接方式导致桶名被重复添加,最终生成了格式错误的URL。
分步解决
修正环境变量中的端点地址
将SPACES_ENDPOINT_URL改为区域级端点,不要包含桶名:SPACES_ENDPOINT_URL=https://nyc3.digitaloceanspaces.com修正Django中的
MEDIA_URL配置
虚拟寻址模式下,django-storages会自动将桶名拼接至URL,因此需要调整MEDIA_URL的生成方式:# 替换原有的MEDIA_URL配置 MEDIA_URL = f"{AWS_S3_ENDPOINT_URL}/{AWS_STORAGE_BUCKET_NAME}/"解决签名不匹配问题
如果修改端点后出现SignatureDoesNotMatch,请检查以下几点:- 确认
AWS_S3_REGION_NAME与端点区域完全一致(此处为nyc3) - 确保
AWS_S3_SIGNATURE_VERSION保持为s3v4 - 验证访问密钥和密钥无额外空格或特殊字符,且权限正确
- 确认
AWS_STORAGE_BUCKET_NAME与DigitalOcean Spaces中的桶名完全匹配
- 确认
可选:优化自定义存储类
若使用自定义MediaStorage,可显式指定配置参数避免自动拼接问题:class MediaStorage(S3Boto3Storage): location = '' bucket_name = settings.AWS_STORAGE_BUCKET_NAME endpoint_url = settings.AWS_S3_ENDPOINT_URL
内容的提问来源于stack exchange,提问作者Jeff
相关产品推荐
相关产品推荐

