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

React Native Web对接EC2上Nginx+Django服务出现CORS错误如何解决?

核心问题排查

1. 前端请求配置错误

CORS 相关的Access-Control-Allow-*头是服务端返回的响应头,前端请求中主动添加这些头属于错误操作,会被浏览器视为自定义请求头,触发额外的预检规则,甚至直接导致校验失败。
同时你开启了凭据传递,根据浏览器CORS规则,这种情况下服务端的Access-Control-Allow-Origin不能设置为*,必须返回和请求Origin完全匹配的域名,否则校验直接不通过。
另外你混淆了不同请求库的参数:withCredentials是XHR/axios的凭据参数,fetch API对应的参数是credentials: "include",参数写错也会导致凭据传递失效。

2. Nginx配置冲突&规则错误

你同时在Nginx和Django两层配置CORS规则,且Nginx做了如下错误配置:

  • proxy_hide_header Access-Control-Allow-Origin会先把Django返回的合法CORS头删除
  • 自行添加的Access-Control-Allow-Origin '*'和凭据传递要求冲突
  • 仅给Access-Control-Allow-Credentials加了always参数,其他CORS头默认只在200/201等状态码下返回,OPTIONS预检请求(通常返回200/204)不会携带这些头,直接导致预检失败。

3. Django配置冗余冲突

你同时开启了CORS_ORIGIN_ALLOW_ALL = True、CORS_ALLOWED_ORIGINS = ['*']、CORS_ALLOWED_ORIGIN_REGEXES三个规则,且未适配凭据传递的要求,虽然django-cors-headers在CORS_ORIGIN_ALLOW_ALL = True且开启凭据支持时会自动返回请求对应的Origin值,但被上层Nginx覆盖为*,完全失效。


修复步骤

步骤1:清理前端请求代码

删除所有Access-Control-Allow-开头的请求头,调整后代码如下:

fetch(`https://${env.apiUrl}/api/v1/user`, {
  method: "GET",
  mode: "cors",
  credentials: "include",
  headers: {
    Authorization: await getToken(),
  },
})

步骤2:简化Nginx配置,删除CORS相关配置

推荐直接用django-cors-headers处理CORS规则,更灵活不易出错,调整Nginx配置如下:

location / {
    proxy_pass http://web/;
    proxy_redirect     off;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme; # 让Django识别请求协议,避免cors头返回协议错误
}

步骤3:修正Django CORS配置

删除冗余配置,明确允许的前端域名,适配凭据要求:

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware', # 注意CorsMiddleware必须放在CommonMiddleware之前
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
     ....
    ]
# 关闭全局允许,明确指定允许的域名
CORS_ORIGIN_ALLOW_ALL = False
# 按实际情况添加前端域名,协议、域名、端口必须完全匹配,多个域名用逗号分隔
CORS_ALLOWED_ORIGINS = [
    'http://localhost:19006', # 本地RN Web的调试地址
    'https://你的线上前端域名.com'
]
ALLOWED_HOSTS = ['*']
CORS_ALLOW_CREDENTIALS = True
# 剩下的CORS_ALLOW_METHODS、CORS_ALLOW_HEADERS保持原有配置即可,不需要的规则可直接删除

步骤4:验证配置

重启Nginx和Django服务后,用curl重新发起OPTIONS请求,检查响应头中是否存在Access-Control-Allow-Origin,值是否和你传入的Origin完全一致,且Access-Control-Allow-Credentials为true。


可选:Nginx直接处理CORS的配置参考

如果不想用Django处理CORS,可直接用Nginx配置,无需保留Django的django-cors-headers相关配置,Nginx配置参考如下:

location / {
    # 处理预检请求
    if ($request_method = OPTIONS) {
        add_header Access-Control-Allow-Origin $http_origin always;
        add_header Access-Control-Allow-Credentials true always;
        add_header Access-Control-Allow-Methods "GET,PUT,POST,DELETE,OPTIONS" always;
        add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization" always;
        return 204;
    }
    # 普通请求加头
    add_header Access-Control-Allow-Origin $http_origin always;
    add_header Access-Control-Allow-Credentials true always;

    proxy_pass http://web/;
    proxy_redirect     off;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:06:03