Django回应CSRF问题
使用Django作为后端构建我的第一个应用程序,并将React作为前端 在本地,我分别在端口8000和3000上运行 我在网上找到了一小段代码,帮助我测试我的CSRF和CORS策略是否设置正确:Django回应CSRF问题,django,reactjs,django-cors-headers,Django,Reactjs,Django Cors Headers,使用Django作为后端构建我的第一个应用程序,并将React作为前端 在本地,我分别在端口8000和3000上运行 我在网上找到了一小段代码,帮助我测试我的CSRF和CORS策略是否设置正确: const API_HOST = 'http://localhost:8000'; let _csrfToken = null; async function getCsrfToken() { if (_csrfToken === null) { const response = awa
const API_HOST = 'http://localhost:8000';
let _csrfToken = null;
async function getCsrfToken() {
if (_csrfToken === null) {
const response = await fetch(`${API_HOST}/csrf/`, {
credentials: 'include',
});
const data = await response.json();
_csrfToken = data.csrfToken;
}
return _csrfToken;
}
async function testRequest(method) {
const response = await fetch(`${API_HOST}/ping/`, {
method: method,
headers: (
method === 'POST'
? {'X-CSRFToken': await getCsrfToken()}
: {}
),
credentials: 'include',
});
const data = await response.json();
return data.result;
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
testGet: 'KO',
testPost: 'KO',
};
}
async componentDidMount() {
this.setState({
testGet: await testRequest('GET'),
testPost: await testRequest('POST'),
});
}
render() {
return (
<div>
<p>Test GET request: {this.state.testGet}</p>
<p>Test POST request: {this.state.testPost}</p>
</div>
);
}
}
export default App;
我怀疑我的问题在那个白名单的某个地方,但我现在不知道它是什么
如果有人能帮助我了解发生了什么,如果他们没有答案,那可能会触发一个“啊哈”时刻。您是否尝试过从实际的cookie中获取CSRF令牌,而不是向服务器发出请求? 因为实际上,您现在正在做的是在每次尝试获取任何内容时获取CSRF令牌 在JavaScript中尝试以下操作:
import Cookies from 'js-cookie;
async function testRequest(method) {
const headers = {};
const csrftoken = Cookies.get('csrftoken'); // or the value from settings.CSRF_COOKIE_NAME
if (csrftoken) {
headers['X-CSRFTOKEN'] = csrftoken;
}
const response = await fetch(`${API_HOST}/ping/`, {
method,
headers,
credentials: 'include',
});
const data = await response.json();
return data.result;
}
除了@tgdn建议从cookie中获取令牌外,我还建议检查您的
SameSite
策略设置,因为将其设置为Strict
或Lax
也会阻止跨源请求中发送的cookie(这可能会导致您的会话丢失/注销等…).我不知道您到底是如何发送cors头的-实际上不允许使用列表,所以您应该始终返回确切的域。但它会在控制台中生成正常响应和错误,其中包含有关cors的信息,而不是403。我猜您在检索csrf令牌时出错,请尝试调试此部分。我没有完全遵循。t发送标头时会附带以下内容:标头:(method=='POST'?{'X-CSRFToken':wait getCsrfToken()}:{}),凭据:'include',});我可以确认正在发送令牌(至少据我所知是这样),我将截图并将其添加到OP中。截图显示发送一个名为X-CSRFToken
的标题,但不是cookie本身。您能否确认,当本地一切正常时,也会发送cookie?也许你也可以为一个工作请求添加一个请求标题的屏幕截图?@BernhardVallant我已经用屏幕进行了更新,现在正在尝试下面的答案。我已经设法让这个在本地工作,类似于我已经拥有的代码,但当我尝试远程时,我会遇到与以前相同的问题,Django拒绝该请求,给出的原因是没有设置CSRF cookie。我的浏览器在cookies部分设置了cookie。接下来,我要看看@Bernhard Vallant的建议是否是我的错误所在。好吧,也许是晚上的时候,或者是我正在与流感作斗争,但我似乎无法理解设置这个的正确位置。根据文档所说,如果我理解正确,默认设置是限制性最小的?否限制性最小的设置是使用None
禁用它。也许试一下,看看它是否能解决你的问题Lax
仍然不允许在跨源请求中发送cookie。。。根据你的新屏幕截图,SameSite=Lax似乎得到了应用。我还没有修复它,但你最后的评论最终让我感到很满意。它在本地工作,因为我的两个开发服务器都使用本地主机运行,只是一个不同的端口,所以SameSite永远不会启动,但只要我尝试远程启动它。我一找到放这个的地方就马上报告!快速更新,我忘了提到我的GET请求通过,即使是远程的,失败的是POST请求,将更新OP。似乎适合SameSite
策略应该阻止CSRF prove请求,如POST
。
import Cookies from 'js-cookie;
async function testRequest(method) {
const headers = {};
const csrftoken = Cookies.get('csrftoken'); // or the value from settings.CSRF_COOKIE_NAME
if (csrftoken) {
headers['X-CSRFTOKEN'] = csrftoken;
}
const response = await fetch(`${API_HOST}/ping/`, {
method,
headers,
credentials: 'include',
});
const data = await response.json();
return data.result;
}