Django+Vue3跨域报错:Access-Control-Allow-Origin相关CORS问题
问题概述
前端Vue3向Django REST API发起请求时,先后出现两个CORS相关错误:
- 初始错误:
Access to XMLHttpRequest at 'https://api.iyziwell.com/api/user/login' from origin 'https://main.d398abgajqt044.amplifyapp.com' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
- 调整配置后新错误:
Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
Postman请求正常,说明API本身逻辑无问题,问题出在CORS配置和请求处理流程上。
错误原因分析与修复步骤
1. 修复CORS中间件配置问题
你的MIDDLEWARE配置存在两个关键问题:
corsheaders.middleware.CorsMiddleware位置错误,必须放在django.middleware.common.CommonMiddleware之前,否则CORS响应头无法正确生效。- 重复添加了
django.middleware.common.CommonMiddleware,会导致请求处理逻辑混乱。
修改后的MIDDLEWARE配置:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', # 移至此处,放在CommonMiddleware之前 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
2. 清理冲突的CORS配置
当前CORS配置存在冲突项:
CORS_ORIGIN_ALLOW_ALL_ORIGINS = True和CORS_ALLOWED_ORIGINS不能同时启用,前者会覆盖后者,导致精确域名白名单失效。CORS_ALLOWED_ORIGIN_REGEXES要求值为正则表达式字符串,当前普通域名字符串无法匹配。
根据需求选择一种配置方案:
方案A:仅允许指定域名(生产环境推荐)
# 关闭全局允许,启用精确域名白名单 CORS_ORIGIN_ALLOW_ALL_ORIGINS = False CORS_ALLOW_CREDENTIALS = True CORS_ALLOWED_ORIGINS = [ 'https://main.d398abgajqt044.amplifyapp.com', 'http://localhost:8082', ] # 如需正则匹配(如子域名)才启用此项,否则可删除 # CORS_ALLOWED_ORIGIN_REGEXES = [ # r'^https://main\.d398abgajqt044\.amplifyapp\.com$', # r'^http://localhost:8082$', # ] CORS_ALLOW_HEADERS = ( 'accept', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', )
方案B:允许所有域名(仅开发环境使用)
CORS_ORIGIN_ALLOW_ALL_ORIGINS = True CORS_ALLOW_CREDENTIALS = True # 此时可删除CORS_ALLOWED_ORIGINS和CORS_ALLOWED_ORIGIN_REGEXES CORS_ALLOW_HEADERS = ( 'accept', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', )
3. 解决预检请求重定向问题
预检请求(OPTIONS请求)不允许被重定向,常见原因及修复:
原因1:URL路径末尾斜杠不一致
Django默认会自动重定向不带斜杠的URL到带斜杠版本。你的urls.py中path('api/user/login', ...)无末尾斜杠,若前端请求URL带斜杠(或反之),会触发重定向。
修复:统一URL格式,修改urls.py:
path('api/user/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
同时确保前端请求路径与后端一致。
原因2:反向代理重定向拦截
若API使用Nginx等反向代理,需确保不对OPTIONS请求做重定向。例如Nginx配置添加:
if ($request_method = OPTIONS) { return 204; }
原因3:Django的HTTPS强制重定向
检查settings.py中SECURE_SSL_REDIRECT配置:
# 生产环境HTTPS保持True,开发环境HTTP设为False SECURE_SSL_REDIRECT = True
4. 检查前端请求头配置
初始错误提到access-control-allow-origin请求头不被允许,是因为前端错误地将该响应头作为请求头发送。Access-Control-Allow-Origin是服务器响应头,无需前端添加,检查Vue请求拦截器或配置,移除该请求头设置。
验证步骤
- 重启Django服务器,确保配置生效。
- 用浏览器开发者工具查看OPTIONS预检请求的响应头,确认包含正确的
Access-Control-Allow-Origin、Access-Control-Allow-Headers等信息。 - 重新发起登录请求,确认跨域错误消失。
内容的提问来源于stack exchange,提问作者Burak Demirer

