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

Django CORS Headers对POST请求失效,求解决方法

问题分析与解决方案

问题核心原因

GET属于简单请求,浏览器不会发送预检OPTIONS请求,直接执行请求并校验返回头;而POST(尤其是带自定义头或非默认Content-Type的POST)属于非简单请求,浏览器会先发送OPTIONS预检请求,确认服务器允许该请求方法、头信息后才会发送实际POST请求。你遇到的问题本质是OPTIONS预检请求未被正确处理,导致浏览器判定CORS不通过。

分步解决步骤

1. 修正Django中间件顺序

django-cors-headers的中间件必须放在最前面(至少在CommonMiddleware之前),否则无法正确拦截并处理预检请求:

# settings.py
MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",  # 必须放在首位
    "django.middleware.common.CommonMiddleware",
    # 其他中间件(如CsrfViewMiddleware等)放在后面
]

2. 补全Django CORS配置

确保settings.py中CORS相关配置完整,覆盖必要的规则:

# settings.py
# 指定允许的前端域名(生产环境禁用CORS_ALLOW_ALL_ORIGINS,用具体域名更安全)
CORS_ALLOWED_ORIGINS = [
    "https://你的前端域名.com",
]
# 显式声明允许的请求方法(默认已包含POST,配置后更清晰)
CORS_ALLOW_METHODS = ("DELETE", "GET", "OPTIONS", "PATCH", "POST", "PUT")
# 允许前端传递的请求头(根据实际业务添加,比如Content-Type、Authorization)
CORS_ALLOW_HEADERS = ("Content-Type", "Authorization")
# 如果前端请求需要携带Cookie,开启此项
CORS_ALLOW_CREDENTIALS = True

3. 调整Apache配置,确保OPTIONS请求被正确转发

当前Apache配置未处理OPTIONS预检请求,可能直接拦截导致无法到达Django。在VirtualHost中添加以下规则:

<VirtualHost *:443>
    ServerName [...]

    # 新增处理OPTIONS请求的规则
    <Location "/">
        Require all granted
        
        # 若Django已通过cors-headers处理CORS,可注释以下Header配置避免重复
        # Header always set Access-Control-Allow-Origin "https://你的前端域名.com"
        # Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, PUT, DELETE, PATCH"
        # Header always set Access-Control-Allow-Headers "Content-Type, Authorization"
        
        # 让OPTIONS请求直接返回200(或转发给Django处理)
        RewriteEngine On
        RewriteCond %{REQUEST_METHOD} OPTIONS
        RewriteRule ^(.*)$ $1 [R=200,L]
    </Location>

    ProxyPass /.well-known !
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/
    ProxyPreserveHost On

    # 原有SSL配置...
    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/[...]/cert.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/[...]/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/[...]/fullchain.pem

    Alias /.well-known [...]/www/.well-known/
    <Directory [...]/www/.well-known>
        Options FollowSymLinks MultiViews
        AllowOverride All
        Require all granted
    </Directory>

    LogLevel debug
    ErrorLog [...]/logs/error.log
    CustomLog [...]/logs/access.log combined
</VirtualHost>

4. 验证请求链路

查看Django的日志文件,确认OPTIONS请求是否被接收并处理:

  • 如果日志中存在OPTIONS请求记录,说明问题出在Django的CORS配置,重新核对CORS_ALLOWED_ORIGINS等参数;
  • 如果日志中没有OPTIONS请求,说明Apache未转发该请求,需重新检查Apache的Rewrite规则和Proxy配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:23:12