django-cors-headers 未放行允许来源请求:NextJS前端无法获取Django后端用户数据
看起来你遇到的核心问题是301重定向导致的CORS头缺失,而不是django-cors-headers本身没配置对——毕竟你的JWT请求能正常工作,说明基础CORS配置是有效的。我们一步步来拆解:
问题根源分析
错误信息里明确提到Status code: 301,这说明你的请求被Django后端做了重定向(通常是URL末尾斜杠的匹配问题)。当浏览器收到301响应时,会自动跳转到重定向地址,但这个重定向响应的CORS头没有正确设置,所以浏览器触发了跨域错误。
为什么JWT请求没问题?因为你请求的/api/token(POST方法)刚好匹配Django的URL规则(不带末尾斜杠),没有触发重定向,所以CORS头正常返回。
具体解决方案
1. 修正Next.js的重定向配置
你的redirects配置里,destination末尾多了一个斜杠,这会导致路径拼接出错:
async redirects() { return [ { source: '/api/:path*', // 去掉末尾的斜杠,避免重复拼接导致路径异常 destination: 'http://localhost:8000/:path*', permanent: false, // 先改成临时重定向,避免浏览器缓存301规则 }, ] },
解释:/:path*已经会把/api/users/1里的users/1完整传递过去,再加末尾斜杠会变成users/1/,如果Django的URL规则是不带斜杠的,就会触发301重定向到带斜杠的版本(反之亦然)。
2. 确保Django的CORS配置覆盖重定向场景
虽然你设置了CORS_ALLOW_ALL_ORIGINS = True,但django-cors-headers默认不会在重定向响应里添加CORS头,需要开启额外配置:
# 在settings.py里添加或修改以下配置 CORS_ALLOW_CREDENTIALS = True # 让重定向响应也能携带CORS头 CORS_PREFLIGHT_MAX_AGE = 86400 # 确保重定向后的请求也被CORS规则覆盖 CORS_REPLACE_HTTPS_REFERER = True
另外,检查Django的APPEND_SLASH设置(默认是True):如果你的URLconf里的路径是带斜杠的,Django会自动把不带斜杠的请求重定向到带斜杠的版本。如果不想用这个特性,可以设置APPEND_SLASH = False,但需要确保所有URL规则和前端请求的URL完全一致。
3. 调整前端请求的URL格式
确保前端请求的URL和Django的URL规则完全匹配:
- 如果Django的URL是
path('users/<int:pk>/', views.UserDetail.as_view())(带斜杠),前端请求就用/api/users/${userId}/(带斜杠) - 如果Django的URL是
path('users/<int:pk>', views.UserDetail.as_view())(不带斜杠),前端就用/api/users/${userId}(不带斜杠)
4. 验证中间件顺序
确认django-cors-headers的中间件放在CommonMiddleware之前,这样才能在重定向响应生成前添加CORS头:
MIDDLEWARE = [ # ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ... ]
测试验证
修改配置后,重启Next.js和Django服务,然后:
- 打开浏览器开发者工具的Network面板,确认请求不再返回301状态码
- 检查响应头里是否包含
Access-Control-Allow-Origin字段
内容的提问来源于stack exchange,提问作者user9808476




