Django React CSRF 问题
Django React CSRF Issues
使用 Django 作为后端并使用 React 作为前端构建我的第一个应用程序。
在本地,我在端口 8000 和 3000 上分别有 运行ning。
我在网上找到了一小段代码来帮助我测试我的 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".
但是,在控制台中,我可以看到 headers 确实在发送 X-CSRFToken。
我有一个 "live" 版本的后端,我也尝试利用它获得与本地相同的结果。
只有在我自己的计算机上进行测试才能获得成功的测试,两个开发服务器都位于该计算机上。
Django 设置:
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = ['localhost:3000', 'My_Public_Ip:3000']
我怀疑我的问题出在该白名单中的某处,但此时我不知道是什么问题。
如果有人可以帮助我了解正在发生的事情,如果他们没有答案,那可能会触发一个 "aha" 时刻。
您是否尝试过从实际的 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
策略设置 CSRF- and Session- Cookie,将其设置为 Strict
或 Lax
还将禁止在跨源请求中发送 cookie(这可能会导致您的 session/being 丢失,注销等...)。
使用 Django 作为后端并使用 React 作为前端构建我的第一个应用程序。
在本地,我在端口 8000 和 3000 上分别有 运行ning。
我在网上找到了一小段代码来帮助我测试我的 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".
但是,在控制台中,我可以看到 headers 确实在发送 X-CSRFToken。
我有一个 "live" 版本的后端,我也尝试利用它获得与本地相同的结果。
只有在我自己的计算机上进行测试才能获得成功的测试,两个开发服务器都位于该计算机上。
Django 设置:
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = ['localhost:3000', 'My_Public_Ip:3000']
我怀疑我的问题出在该白名单中的某处,但此时我不知道是什么问题。
如果有人可以帮助我了解正在发生的事情,如果他们没有答案,那可能会触发一个 "aha" 时刻。
您是否尝试过从实际的 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
策略设置 CSRF- and Session- Cookie,将其设置为 Strict
或 Lax
还将禁止在跨源请求中发送 cookie(这可能会导致您的 session/being 丢失,注销等...)。