【发布时间】:2019-05-31 11:07:19
【问题描述】:
使用 Django 作为后端并使用 React 作为前端来构建我的第一个应用程序。
在本地,我分别在 8000 和 3000 端口上运行。
我在网上找到了一个简短的 sn-p 代码,可帮助我测试我的 CSRF 和 CORS 策略是否设置正确:
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;
编辑澄清:远程 GET 请求通过,只有 POST 失败
当我在本地运行此代码时,我得到了正确的响应,即当响应返回有效时,“KO”变为“OK”。
这只适用于我的机器。如果我尝试从网络中的任何其他机器访问它,我会收到以下错误:
403 禁止
Django的调试原因是“CSRF cookie not set”。
但是,在控制台中,我可以看到标头确实在发送 X-CSRFToken。
我有一个“实时”版本的后端,我也尝试过使用它,结果与本地相同。
只有在我自己的计算机上尝试时,我才能获得成功的测试,这两个开发服务器都坐在那里。
Django 设置:
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = ['localhost:3000', 'My_Public_Ip:3000']
我怀疑我的问题在那个白名单中的某个地方,但我现在不知所措。
如果有人可以帮助我了解正在发生的事情,如果他们没有答案,那可能会引发“啊哈”时刻。
【问题讨论】:
-
我不知道您如何准确发送 cors 标头 - 实际上不允许使用列表,因此您应该始终返回确切的域。但它会在控制台中生成正常响应和错误,其中包含有关 cors 的信息,而不是 403。我猜你在检索该 csrf 令牌时做错了,尝试调试这部分。
-
我没有完全按照。标头是这样发送的: headers: ( method === 'POST' ? {'X-CSRFToken': await getCsrfToken()} : {} ), credentials: 'include', });我可以确认正在发送令牌(至少在我的理解中是这样),我将截屏并将其添加到 OP。
-
截图显示发送一个名为
X-CSRFToken的标头,但不是cookie本身。你能确认当一切都在本地正常工作时,还会发送一个 cookie 吗?也许您还可以为工作请求添加请求标头的屏幕截图? -
@BernhardVallant 我已经更新了屏幕,现在在下面尝试你的答案。
标签: django reactjs django-cors-headers