django默认拒绝跨域请求是因为未配置cors响应头,浏览器基于同源策略主动拦截;需用django-cors-headers中间件配置cors_allowed_origins等参数,带credentials时须禁用通配符并启用cors_allow_credentials。

为什么 Django 默认拒绝跨域请求
Django 本身不内置 CORS 支持,django.middleware.csrf.CsrfViewMiddleware 和默认的响应头(如缺失 Access-Control-Allow-Origin)会让浏览器直接拦截前端发来的跨域 fetch 或 axios 请求。这不是 bug,是浏览器同源策略的主动拦截——后端没明确说“允许谁来调我”,浏览器就按最严策略拦掉。
常见错误现象:Failed to load http://api.example.com/xxx: No 'Access-Control-Allow-Origin' header is present on the requested resource.
关键点:CORS 是浏览器强制执行的前端限制,服务端不配响应头,前端再怎么改 mode: 'cors' 都会失败。
用 django-cors-headers 快速启用全局跨域
别手写中间件,django-cors-headers 是事实标准,维护活跃、适配新版 Django(包括 4.x / 5.x)、支持细粒度控制。
安装与注册:
pip install django-cors-headers
在 settings.py 中:
- 把
'corsheaders'加到INSTALLED_APPS开头附近(避免被其他 app 覆盖) - 把
'corsheaders.middleware.CorsMiddleware'插入到CommonMiddleware之前(必须早于它,否则响应头可能被覆盖) - 配置允许来源:
CORS_ALLOWED_ORIGINS = ['http://localhost:3000', 'https://myapp.com']
注意:CORS_ALLOW_ALL_ORIGINS = True 仅用于开发,生产环境禁用——它等价于返回 Access-Control-Allow-Origin: *,但会阻止带凭证(如 cookies、Authorization)的请求。
带 credentials 的请求必须精确匹配 origin
前端若设置了 credentials: 'include'(比如要传 sessionid 或 token),后端就不能用通配符 *,且必须显式返回请求中的 origin 值。
常见踩坑:
- 误配
CORS_ALLOW_ALL_ORIGINS = True后又加credentials: 'include'→ 浏览器报错The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. - 漏配
CORS_ALLOW_CREDENTIALS = True→ 响应头缺Access-Control-Allow-Credentials: true,前端收不到 cookie - 前端 origin 是
http://localhost:3000,但后端只写了http://localhost→ 不匹配,被拒
正确做法:用 CORS_ALLOWED_ORIGINS 列出完整协议+域名+端口,并设 CORS_ALLOW_CREDENTIALS = True。
API 视图级控制比全局配置更安全
不是所有接口都该跨域。比如管理后台的 /admin/ 或内部健康检查 /health/,暴露给任意 origin 就是风险。
用装饰器精准控制:
from corsheaders.decorators import cors_allow_all
然后在视图上加:
-
@cors_allow_all:允许任意 origin(仍受CORS_ALLOW_CREDENTIALS约束) - 或自定义装饰器,比如只允许可信域名:
@cors_origin_regex(r'^https?://(myapp\.com|staging\.myapp\.com)$')
注意:django-cors-headers 的装饰器只对函数视图生效;类视图需用 @method_decorator 包裹,或继承 CorsMixin。
复杂点在于:如果用了 DRF,还要注意 APIView 的 permission_classes 和 CORS 控制的执行顺序——CORS 中间件在权限校验之前,所以跨域失败不会触发权限拒绝逻辑,这点容易被忽略。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











