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

React+Django单登录应用403错误及CSRF Token、参数传递问题求助

React + Django 登录请求403及参数获取问题修复

问题描述

开发React+Django单点登录应用时,前端发POST请求到后端出现403错误,同时后端无法正确获取前端传递的账号密码。以下是原始代码:

原始前端React代码

const LoginPage = () => {
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')

  const handlelogin = async () => {
    function getCookie(name) {
      let cookieValue = null;
      if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
          const cookie = cookies[i].trim();
          if (cookie.substring(0, name.length + 1) === (name + '=')) {
            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
            break;
          }
        }
      }
      return cookieValue;
    }
    const csrftoken = getCookie('csrftoken');

    await fetch('http://localhost:8000/auth/login',    
      {
        method: "POST",
        headers: {
          "X-CSRFToken": csrftoken
        }, 
        body: {
          " username": username, 
          "password": password
        }
      }
    ).then(res => res.json()).then(data => console.log(data))
  }

  return (
    <div>
      <div className=" mx-auto">
        <h1 className=" font-bold sm:text-2xl md:text-3xl p-6 font-serif"> Tailwindcss Login Card</h1>

        <div className="card" >
          <label className=" font-bold">Username:</label>
          <input 
            type="text" 
            placeholder="Enter username" 
            className="inputs"
            onChange={(e)=>{ setUsername(e.target.value)}}
          />
          <label className=" font-bold">Password:</label>
          <input 
            type="password" 
            placeholder="Enter password" 
            className="inputs"
            onChange={(e) => {setPassword(e.target.value)}}
          />
          <button className="buttons" onClick={handlelogin}>Login</button>
          <p className=' text-center'>
            Sign up if you don't have an account
          </p>
          <button className="buttons bg-blue-600 active:bg-blue-800">Sign Up</button>
        </div>
       
        <div className=" mt-5 text-right hover:scale-105 hover:text-blue-700">
          <a  href="/" >Forgot Password?</a>
        </div>

      </div>
    </div>
  )
}

export default LoginPage

原始后端Django代码

def login(request):
    username = request.body.username
    password = request.body.password
    user = authenticate(request, username=username, password=password)
    if user is not None:
        login(request, user)
        return JsonResponse({'response':'you have successfully put reached here'})
    else:
        return JsonResponse('you are not allowed here')

问题修复

1. 解决CSRF Token 403错误

导致403的核心问题有两个:

  • fetch默认不会携带Cookie,Django无法验证CSRF Token合法性
  • 请求体未以JSON格式传递,且缺少Content-Type头

修改后的前端请求配置:

await fetch('http://localhost:8000/auth/login',    
  {
    method: "POST",
    credentials: 'include', // 携带Cookie,确保Django能匹配CSRF Token对应的Cookie
    headers: {
      "X-CSRFToken": csrftoken,
      "Content-Type": "application/json" // 指定请求体为JSON格式
    }, 
    body: JSON.stringify({
      "username": username, // 去掉键名前的空格,避免后端无法匹配
      "password": password
    })
  }
).then(res => res.json()).then(data => console.log(data))

若前后端跨域(如端口不同),需在Django中配置CORS:
安装django-cors-headers后,修改settings.py:

INSTALLED_APPS = [
    # ...
    'corsheaders',
]

MIDDLEWARE = [
    # ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
]

CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000", # 替换为你的前端地址
]

2. 后端正确获取请求参数

request.body是原始字节流,不能直接通过.访问属性,需先解析为JSON对象:
修改后的后端代码:

import json
from django.http import JsonResponse
from django.contrib.auth import authenticate, login

def login_view(request): # 避免和内置login函数重名
    if request.method != 'POST':
        return JsonResponse({'error': 'Method not allowed'}, status=405)
    
    try:
        data = json.loads(request.body)
        username = data.get('username')
        password = data.get('password')
    except json.JSONDecodeError:
        return JsonResponse({'error': 'Invalid JSON'}, status=400)
    
    user = authenticate(request, username=username, password=password)
    if user is not None:
        login(request, user)
        return JsonResponse({'response': 'Login successful'})
    else:
        return JsonResponse({'response': 'Invalid credentials'}, status=401)

3. 额外注意事项

  • 确保Django内置的csrf中间件已启用:django.middleware.csrf.CsrfViewMiddleware在MIDDLEWARE列表中
  • 前端的getCookie函数逻辑正确,可正常获取CSRF Token

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 14:44:52