django跨域配置
为了解决 Django 项目的跨域请求(CORS)问题,尤其是在企业级环境中,推荐使用 django-cors-headers
中间件,并结合环境隔离、安全白名单、速率限制等策略进行配置。以下是完整的企业级解决方案:
第一步:安装中间件
pip install django-cors-headers
第二步:配置 Django 项目
在 settings.py
中添加:
1. 添加到 INSTALLED_APPS
INSTALLED_APPS = [...'corsheaders',...
]
2. 添加到 MIDDLEWARE
(务必靠前)
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', # 必须放在最前面之一'django.middleware.common.CommonMiddleware',...
]
第三步:企业级 CORS 策略配置
1. 生产环境使用白名单域名
CORS_ALLOWED_ORIGINS = ["https://app.example.com","https://admin.example.com",
]
或者使用正则表达式:
CORS_ALLOWED_ORIGIN_REGEXES = [r"^https://\w+\.example\.com$",
]
当你在 Django 中配置了 CORS_ALLOWED_ORIGINS
白名单后,只有这些域名才能成功发起跨域请求(如 fetch
或 axios
请求)。如果请求的来源域名不在白名单中,浏览器会拦截请求,显示 CORS 错误,比如你之前看到的:
No 'Access-Control-Allow-Origin' header is present...
举个例子:
CORS_ALLOWED_ORIGINS = ["https://app.example.com","https://admin.example.com",
]
✅ 来自
https://app.example.com
的请求:允许跨域访问❌ 来自
http://localhost:8080
或https://evil.com
的请求:被浏览器拦截,无法访问
🚫 注意:不是后端拒绝,而是浏览器拦截
后端其实是可以收到请求的,但如果没有返回正确的 CORS 响应头,浏览器会阻止前端访问响应内容。这是浏览器的安全机制。
✅ 企业级建议
开发环境可以使用
CORS_ALLOW_ALL_ORIGINS = True
放宽限制生产环境必须使用白名单,防止恶意网站滥用你的 API
如果你有多个前端子域名,建议使用正则匹配:
CORS_ALLOWED_ORIGIN_REGEXES = [r"^https://.*\.example\.com$",
]
2. 控制允许的方法和头部
CORS_ALLOW_METHODS = ["GET","POST","OPTIONS",
]CORS_ALLOW_HEADERS = ["authorization","content-type","x-requested-with",
]
在 Django 项目中使用 django-cors-headers
中间件时,你可以通过 CORS_ALLOW_METHODS
和 CORS_ALLOW_HEADERS
来精细控制哪些 HTTP 方法和请求头可以被跨域访问。这是企业级安全配置的关键部分。
CORS_ALLOW_METHODS
:允许的 HTTP 方法
默认值如下:
CORS_ALLOW_METHODS = ["DELETE","GET","OPTIONS", # 必须支持,用于预检请求"PATCH","POST","PUT",
]
方法解析:
方法 | 说明 |
---|---|
GET | 获取资源,最常用的读取操作 |
POST | 创建资源或提交数据(如登录、表单) |
PUT | 更新整个资源(幂等) |
PATCH | 局部更新资源(非幂等) |
DELETE | 删除资源 |
OPTIONS | 浏览器预检请求,必须支持以通过 CORS 验证 |
✅ 建议:不要随意移除
OPTIONS
,否则浏览器将无法完成跨域预检。
CORS_ALLOW_HEADERS
:允许的请求头
允许前端在跨域请求中携带这些自定义请求头。
默认值如下:
CORS_ALLOW_HEADERS = ["accept","accept-encoding","authorization","content-type","dnt","origin","user-agent","x-csrftoken","x-requested-with",
]
请求头解析:
请求头 | 说明 |
---|---|
accept | 客户端可接受的响应类型(如 JSON) |
accept-encoding | 支持的压缩算法(如 gzip) |
authorization | 认证令牌(如 JWT、Bearer) |
content-type | 请求体的格式(如 application/json ) |
dnt | “Do Not Track” 隐私请求标志 |
origin | 请求来源域名(由浏览器自动添加) |
user-agent | 客户端信息(浏览器类型等) |
x-csrftoken | Django CSRF 令牌(用于保护 POST 请求) |
x-requested-with | AJAX 请求标志(通常为 XMLHttpRequest ) |
✅ 建议:如果你使用自定义头部(如
X-Auth-Token
),需要手动添加到此列表中。
企业级扩展建议
限制敏感方法:如不需要
DELETE
或PATCH
,可移除以减少攻击面。自定义头部白名单:如使用
debug-token
、x-api-key
等自定义头部,务必添加:CORS_ALLOW_HEADERS += ["x-api-key", "debug-token"]
暴露响应头(可选):
CORS_EXPOSE_HEADERS = ["Content-Disposition", "X-RateLimit-Limit"]
这允许前端访问这些响应头信息。
3. 是否允许携带凭证(如 Cookie)
CORS_ALLOW_CREDENTIALS = True
如果你不设置这个为 True
,即使前端设置了 withCredentials: true
,浏览器也会拒绝发送 Cookie。
第四步:防御恶意请求(可选)
你可以自定义中间件限制 OPTIONS
请求频率,防止滥用:
from corsheaders.middleware import CorsMiddleware
from django.http import HttpResponseTooManyRequests
from django.core.cache import cacheclass ThrottledCorsMiddleware(CorsMiddleware):def process_view(self, request, *args, **kwargs):if request.method == 'OPTIONS':ip = request.META.get('REMOTE_ADDR')if cache.get(f'cors_options_{ip}'):return HttpResponseTooManyRequests()cache.set(f'cors_options_{ip}', True, 60)return super().process_view(request, *args, **kwargs)
然后替换原来的 CorsMiddleware
。
第五步:区分环境配置(推荐)
使用环境变量或配置文件区分开发与生产环境:
import osif os.getenv("DJANGO_ENV") == "production":CORS_ALLOWED_ORIGINS = ["https://app.example.com"]
else:CORS_ALLOW_ALL_ORIGINS = True # 开发环境放宽限制
第六步:确保后端响应 OPTIONS 请求
Django 默认不会处理 OPTIONS
请求。你可以使用 @csrf_exempt
或确保视图支持 OPTIONS
方法,或者使用 DRF 的 APIView
,它会自动处理预检请求。