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

Django认证单URL触发Access-Control-Allow-Origin跨域错误

问题排查与解决方案

问题原因

登录存在的用户时触发CORS错误,本质是带凭据的跨域请求未被服务器正确允许:

  • 当auth.login(request, user)执行成功时,Django会在响应中设置Session Cookie,此时浏览器将该请求判定为「带凭据(Credentials)的请求」。
  • 你的Django配置中未开启CORS_ALLOW_CREDENTIALS,导致服务器返回的CORS响应头缺少Access-Control-Allow-Credentials: true,浏览器出于安全拦截了响应。
  • 登录失败时,没有设置Cookie,请求不属于带凭据的范畴,因此无需该响应头,浏览器正常接收结果。

具体修复步骤

1. 修正Django CORS配置

在settings.py中更新以下配置,建议关闭全局允许所有源以提升安全性:

# 替换原有相关配置
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
  "http://localhost:3000",
  "http://127.0.0.1:3000",
)
# 允许带凭据的跨域请求
CORS_ALLOW_CREDENTIALS = True

2. 重构登录接口(改用POST请求,避免URL传敏感信息)

修改路由

# users/urls.py
urlpatterns = [
  path('login/', login),  # 移除URL中的用户名密码参数
  path('logout/', logout),
  path('info/', info),
]

修改视图

# users/views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.contrib import auth
from rest_framework import status

@api_view(['POST'])  # 改为POST请求
def login(request):
    # 从请求体获取参数
    username = request.data.get('username')
    password = request.data.get('password')
    
    if not username or not password:
        return Response('缺少参数', status=status.HTTP_400_BAD_REQUEST)
    
    user = auth.authenticate(username=username, password=password)
    if user is not None:
        auth.login(request, user)
        return Response('登录成功')
    else:
        return Response('用户名或密码错误', status=status.HTTP_401_UNAUTHORIZED)

3. 修正React的Fetch请求(携带凭据)

// React组件内的请求代码
let [message, setMessage] = useState('waiting...')

// 改用POST请求,参数放在请求体,同时携带凭据
fetch('http://localhost:8000/users/login/', {
  method: 'POST',
  credentials: 'include',  // 关键:跨域时携带Cookie等凭据
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    username: 'Timoty',
    password: 'foo'
  })
})
.then(res => res.text())
.then(text => setMessage(text))
.catch(err => console.error('请求错误:', err))

额外注意事项

  • 生产环境中,务必将CORS_ORIGIN_WHITELIST设置为实际的前端域名,不要使用*或本地地址。
  • 后续的info接口如果需要获取登录状态,同样需要React请求携带credentials: 'include',否则Django无法识别用户会话。
  • 建议使用DRF的SessionAuthentication认证类替代原生auth模块,更符合RESTful规范。

内容的提问来源于stack exchange,提问作者Plegeus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:40:26