如何通过django-cors-headers从数据库动态填充CORS_ORIGIN_WHITELIST?
解决Django动态CORS域名白名单的问题
嘿,这个场景我太熟悉了——django-cors-headers的静态白名单确实没法直接从数据库拉取,毕竟settings在应用启动前就加载完了,模型还没初始化呢。不过有几个实用的办法能搞定这个问题:
方案一:自定义动态CORS中间件
中间件是在请求处理阶段运行的,这时候模型已经完全加载,完全可以查询数据库。我们可以写一个自定义中间件,在每次请求时检查Origin是否在你的Website模型里,再决定是否允许跨域。
步骤1:创建自定义中间件
在你的app下新建middleware.py,写入以下代码:
from django.utils.deprecation import MiddlewareMixin from django.core.cache import cache from your_app.models import Website # 替换成实际的app名 class DynamicCORSOriginMiddleware(MiddlewareMixin): def process_request(self, request): origin = request.META.get('HTTP_ORIGIN') if not origin: return None # 先从缓存取允许的域名(后面会说缓存优化) allowed_origins = cache.get('allowed_cors_origins', []) # 如果缓存没命中,直接查数据库并更新缓存 if not allowed_origins: allowed_origins = list(Website.objects.values_list('domain', flat=True)) cache.set('allowed_cors_origins', allowed_origins, 3600) # 缓存1小时 if origin in allowed_origins: # 告诉django-cors-headers这个Origin是允许的 request.META['CORS_ALLOW_ORIGIN'] = origin return None
步骤2:注册中间件
在settings.py的MIDDLEWARE列表里,把这个自定义中间件放到CorsMiddleware前面:
MIDDLEWARE = [ # ... 其他中间件(比如SecurityMiddleware等) 'your_app.middleware.DynamicCORSOriginMiddleware', 'corsheaders.middleware.CorsMiddleware', # ... 其他中间件 ]
方案二:自动更新缓存(可选优化)
上面的方案用了缓存减少数据库查询,但如果Website模型的域名有更新,缓存不会自动同步。我们可以用Django信号来解决这个问题:
步骤1:创建信号处理函数
在app下新建signals.py:
from django.db.models.signals import post_save, post_delete from django.dispatch import receiver from django.core.cache import cache from your_app.models import Website @receiver([post_save, post_delete], sender=Website) def refresh_cors_cache(sender, instance, **kwargs): # 当域名添加/修改/删除时,更新缓存 allowed_origins = list(Website.objects.values_list('domain', flat=True)) cache.set('allowed_cors_origins', allowed_origins, 3600)
步骤2:注册信号
在app的apps.py里的ready方法中导入信号:
from django.apps import AppConfig class YourAppConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'your_app' def ready(self): import your_app.signals # 导入信号使其生效
注意事项
- 确保数据库里的
domain字段存储的是完整的Origin(比如https://example.com,而不是只存example.com),否则请求的Origin和数据库值不匹配会导致验证失败。 - 如果你的业务对域名更新的实时性要求极高,可以缩短缓存过期时间,或者在域名变更时手动触发缓存刷新。
内容的提问来源于stack exchange,提问作者sshussain270
相关产品推荐
相关产品推荐

