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

返回非200状态码时出现CORS错误(Django+ReactJS)

Django返回401时React触发CORS报错的解决方法

问题场景

Django后端返回401(未授权)状态码时,React前端触发CORS报错;改为返回200状态码可正常运行,但业务需求必须返回401。

报错信息

Access to fetch at 'http://localhost:8888/employees/api/fetch/home/data/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

前端React请求代码

export async function post(url, requestBody = {}, token=true) {
    try{
        const requestOptions = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'token' : token ? window.sessionStorage.getItem("token") : null,
                'user-type' : token ? window.sessionStorage.getItem("user-type") : null,
                'identifier' : token ? window.sessionStorage.getItem("identifier") : null,
            },
            body: requestBody ? JSON.stringify(requestBody) : "{}"
        };
        console.log("Requesting POST : url is : ", url," Content Is: ", requestOptions)
        const response = await fetch(url, requestOptions);
        return await response.json()
    }catch(e){
        console.log("Service Failed: ", e)
        return {
            status: false,
            messages: ["Service Failed. Please try after sometime."]
        }
    }
}

后端Django配置(settings.py)

#TODO
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
]

CUSTOM_HEADERS = (
    'Access-Control-Allow-Origin',
    'token',
    'user-type',
    'identifier',
    'device-id',
    'is-mobile'
)
CORS_ALLOW_HEADERS = default_headers + CUSTOM_HEADERS

#TODO
CORS_ORIGIN_ALLOW_ALL = True

#TODO
CORS_ORIGIN_WHITELIST = (
    'http://localhost:3000',
)

#TODO
ALLOWED_HOSTS = [
    '127.0.0.1',
    'localhost',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'middleware.authenticate.Authenticate',

    #Cors
    'corsheaders.middleware.CorsMiddleware',
]

Django响应构建函数

def build_response(response_code, message, data=None):
    if (message == None or message == ""):
        message = []
    else:
        if (hasattr(message, '__len__') and (not isinstance(message, str))):
            pass
        else:
            message = [message]
    fdata = {
        "status" : True if response_code < 300 else False,
        "messages" : message,
        "data" :data
    }
    resp =  Response(fdata, response_code)
    
    cust_headers = (','.join(str(each_hdr) for each_hdr in CUSTOM_HEADERS))
    allowed_origins = (','.join(str(each_origin) for each_origin in CORS_ALLOWED_ORIGINS))

    resp['Access-Control-Allow-Origin'] = allowed_origins
    resp["Access-Control-Allow-Headers"] = 'X-Requested-With, Content-Type, '+cust_headers
    return resp

解决方法

  • 调整中间件顺序:corsheaders.middleware.CorsMiddleware必须放在所有其他中间件最前面,尤其是自定义的认证中间件。预检请求(OPTIONS)需要先被CORS中间件处理返回200,不能被认证中间件拦截返回401。修改后的MIDDLEWARE顺序:
    MIDDLEWARE = [
        # Cors中间件前置
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'middleware.authenticate.Authenticate',
    ]
    
  • 跳过OPTIONS请求的认证检查:在自定义的middleware.authenticate.Authenticate中间件中,直接放行OPTIONS请求,避免触发401:
    class Authenticate(MiddlewareMixin):
        def process_request(self, request):
            if request.method == 'OPTIONS':
                return None
            # 原有认证逻辑...
    
  • 清理冗余CORS配置:CORS_ORIGIN_ALLOW_ALL = True已覆盖CORS_ALLOWED_ORIGINS和CORS_ORIGIN_WHITELIST,建议保留CORS_ALLOWED_ORIGINS并设置CORS_ORIGIN_ALLOW_ALL = False,提升安全性。
  • 移除响应中手动添加的CORS头:corsheaders库会自动处理CORS响应头,无需在build_response函数中手动添加,避免重复或错误配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 00:31:04