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
相关产品推荐
相关产品推荐

