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

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。

分步解决

  1. 修正环境变量中的端点地址
    将SPACES_ENDPOINT_URL改为区域级端点,不要包含桶名:

    SPACES_ENDPOINT_URL=https://nyc3.digitaloceanspaces.com
    
  2. 修正Django中的MEDIA_URL配置
    虚拟寻址模式下,django-storages会自动将桶名拼接至URL,因此需要调整MEDIA_URL的生成方式:

    # 替换原有的MEDIA_URL配置
    MEDIA_URL = f"{AWS_S3_ENDPOINT_URL}/{AWS_STORAGE_BUCKET_NAME}/"
    
  3. 解决签名不匹配问题
    如果修改端点后出现SignatureDoesNotMatch,请检查以下几点:

    • 确认AWS_S3_REGION_NAME与端点区域完全一致(此处为nyc3)
    • 确保AWS_S3_SIGNATURE_VERSION保持为s3v4
    • 验证访问密钥和密钥无额外空格或特殊字符,且权限正确
    • 确认AWS_STORAGE_BUCKET_NAME与DigitalOcean Spaces中的桶名完全匹配
  4. 可选:优化自定义存储类
    若使用自定义MediaStorage,可显式指定配置参数避免自动拼接问题:

    class MediaStorage(S3Boto3Storage):
        location = ''
        bucket_name = settings.AWS_STORAGE_BUCKET_NAME
        endpoint_url = settings.AWS_S3_ENDPOINT_URL
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:25:14