React调用Django接口出现CORS跨域错误,已配置corsheaders仍未解决
问题原因&修复方案
1. 修正Django配置错误
ALLOWED_HOSTS配置规则是仅填写域名/IP,不能带协议、端口,你的配置不符合要求,修改为:
ALLOWED_HOSTS = [ "127.0.0.1", "localhost" ]
同时确保CorsMiddleware是MIDDLEWARE列表中的第一个中间件,不能放在其他中间件后面,否则会失效。
如果不需要开放全域名访问,建议关闭CORS_ORIGIN_ALLOW_ALL,只用白名单配置即可:
CORS_ORIGIN_ALLOW_ALL = False CORS_ORIGIN_WHITELIST = [ "http://127.0.0.1:3000", "http://localhost:3000" ]
2. 移除React请求头里的错误配置
Access-Control-Allow-Origin是服务端返回的响应头,在前端请求头里添加该参数完全无效,反而会导致预检请求校验失败,删除axios配置里的这个header:
const headers = { 'Content-Type': 'application/json', }
3. 统一请求路径避免重定向
你axios请求的地址是http://127.0.0.1:8000/login/(带末尾斜杠),fetch请求的地址是http://127.0.0.1:8000/login(不带末尾斜杠)。Django默认开启APPEND_SLASH配置,遇到不带斜杠的匹配路径会返回301重定向到带斜杠的地址,跨域场景下重定向会触发CORS报错,统一所有前端请求地址的末尾斜杠,和Django路由配置保持一致即可。
4. 关于两次请求的说明
你看到的两次请求是浏览器的正常行为:第一次是OPTIONS类型的预检请求,用于校验服务端是否允许跨域访问,校验通过后才会发起第二次正式的POST请求。只要CORS配置正确,预检请求会自动通过,不需要额外处理。如果还是想减少请求,可以配置CORS缓存时间:
# Django settings添加,单位是秒 CORS_PREFLIGHT_MAX_AGE = 86400
5. 视图添加OPTIONS请求处理
部分场景下视图未处理OPTIONS请求也会导致跨域报错,可以修改Django视图兼容:
from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt def Login(request): if request.method == "OPTIONS": return JsonResponse({}, status=200) if request.method == "POST": return JsonResponse({"message" : "Invalid credentials"}, status=401)
补充:CSRF校验处理
Django默认开启CSRF校验,POST请求如果未携带CSRF Token会返回403错误,上述代码中已经添加了@csrf_exempt装饰器跳过校验,适配前后端分离场景的接口调用需求。
内容的提问来源于stack exchange,提问作者Pankaj

