React向Django API发送POST请求遇403禁止错误求助
解决React向Django API发送POST请求的403禁止错误
错误原因
服务器返回的Forbidden (Origin checking failed - http://localhost:3000 does not match any trusted origins.)错误,核心问题有两个:
- Django未将React运行地址
http://localhost:3000加入跨域信任源 - POST请求未携带CSRF令牌,不符合Django的安全验证机制
解决方案步骤
1. 配置Django跨域信任与CORS支持
首先安装处理跨域的库:
pip install django-cors-headers
修改Django项目的settings.py文件,添加以下配置:
# 加入INSTALLED_APPS INSTALLED_APPS = [ # 保留原有应用,新增此行 'corsheaders', ] # 加入MIDDLEWARE(必须放在CommonMiddleware之前) MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # 保留原有中间件 ] # 允许React地址跨域访问 CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", ] # 信任React地址的CSRF请求 CSRF_TRUSTED_ORIGINS = [ "http://localhost:3000", ] # 允许跨域携带Cookie(用于传递CSRF令牌) CORS_ALLOW_CREDENTIALS = True
2. 在React请求中添加CSRF令牌
修改Genre.js,新增获取CSRF令牌的函数,并在POST请求头中携带令牌:
import React, { useState, useEffect } from "react"; // 获取Cookie中的CSRF令牌 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; } function Genres() { const [genres, setGenres] = useState([]); const [clickedGenre, setClickedGenre] = useState(""); const [type, setType] = useState("") useEffect(() => { fetch("http://localhost:8000/api/genres/") .then((response) => response.json()) .then((data) => setGenres(data.genres)) .catch((error) => console.log(error)); }, []); function handleClick(genre) { setClickedGenre(genre); const query_params = { genre: genre, }; const csrftoken = getCookie('csrftoken'); fetch("http://localhost:8000/api/search/", { method: "POST", headers: { "Content-Type": "application/json", "X-CSRFToken": csrftoken, }, body: JSON.stringify(query_params), credentials: 'include', // 确保携带Cookie }) .then((response) => response.json()) .then((data) => console.log(data)) .catch((error) => console.log(error)); } return ( <div> <div className="genre-list-container"> <ul className="genre-list"> {genres.map((genre) => ( <li className="genre" onClick={() => handleClick(genre)} key={genre} > {genre} </li> ))} </ul> </div> </div> ); } export default Genres;
内容的提问来源于stack exchange,提问作者Scottsdaaale
相关产品推荐
相关产品推荐

