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

Angular+Django项目中OPTIONS请求的CORS头配置问题

解决Angular+Django跨域CORS及OPTIONS预检请求问题

核心问题原因

手动给单个GET响应添加CORS头的方式无法覆盖浏览器自动发送的OPTIONS预检请求,Django默认会处理OPTIONS请求但未携带所需的CORS头,导致POST请求被拦截。

推荐解决方案:使用django-cors-headers库

这是Django生态中处理CORS最便捷且规范的方式,无需手动编写中间件:

  1. 安装库
    pip install django-cors-headers
    
  2. 修改settings.py配置
    • 将库添加到INSTALLED_APPS:
      INSTALLED_APPS = [
          # ... 其他已有应用
          'corsheaders',
      ]
      
    • 将CORS中间件添加到MIDDLEWARE(注意顺序要在CommonMiddleware之前):
      MIDDLEWARE = [
          # ... 其他已有中间件
          'corsheaders.middleware.CorsMiddleware',
          'django.middleware.common.CommonMiddleware',
      ]
      
    • 配置允许的前端源(替换为你的Angular服务地址,比如http://localhost:4200):
      CORS_ALLOWED_ORIGINS = [
          "http://localhost:4200",
      ]
      
    • 开启允许携带凭证(对应前端的withCredentials: true):
      CORS_ALLOW_CREDENTIALS = True
      

配置完成后,所有请求(包括OPTIONS预检、GET、POST)都会自动带上正确的CORS头,无需手动处理响应。

自定义中间件方案(不依赖第三方库)

如果不想使用第三方库,可以自己编写全局中间件统一处理所有请求的CORS头:

  1. 在你的Django应用下创建middleware.py文件,添加以下代码:
    from django.utils.deprecation import MiddlewareMixin
    
    class CORSMiddleware(MiddlewareMixin):
        def process_response(self, request, response):
            # 替换为你的Angular服务地址
            response["Access-Control-Allow-Origin"] = "http://localhost:4200"
            response["Access-Control-Allow-Credentials"] = "true"
            
            # 处理OPTIONS预检请求,允许所需的方法和头
            if request.method == "OPTIONS":
                response["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
                response["Access-Control-Allow-Headers"] = "Content-Type, X-CSRFToken"
            
            return response
    
  2. 在settings.py的MIDDLEWARE中添加该中间件(同样放在CommonMiddleware之前):
    MIDDLEWARE = [
        # ... 其他已有中间件
        'your_app_name.middleware.CORSMiddleware',
        'django.middleware.common.CommonMiddleware',
    ]
    

额外注意事项

  • Angular端确保所有需要携带Cookie的请求都设置withCredentials: true,比如POST请求:
    this.http.post(this.url, requestData, { withCredentials: true });
    
  • 处理CSRF令牌:Django的CSRF保护要求POST请求携带X-CSRFToken头,可通过Angular拦截器自动实现:
    import { Injectable } from '@angular/core';
    import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
    
    @Injectable()
    export class CsrfInterceptor implements HttpInterceptor {
      intercept(req: HttpRequest<any>, next: HttpHandler) {
        // 从Cookie中获取csrftoken
        const csrfToken = document.cookie.split('; ')
          .find(row => row.startsWith('csrftoken='))?.split('=')[1];
        
        if (csrfToken) {
          req = req.clone({
            headers: req.headers.set('X-CSRFToken', csrfToken)
          });
        }
        return next.handle(req);
      }
    }
    
    在app.module.ts中注册拦截器:
    import { HTTP_INTERCEPTORS } from '@angular/common/http';
    import { CsrfInterceptor } from './csrf.interceptor';
    
    @NgModule({
      // ... 其他配置
      providers: [
        { provide: HTTP_INTERCEPTORS, useClass: CsrfInterceptor, multi: true }
      ]
    })
    export class AppModule { }
    

内容的提问来源于stack exchange,提问作者bp-pet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 21:50:12