Django回应CSRF问题

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

使用Django作为后端构建我的第一个应用程序,并将React作为前端

在本地,我分别在端口8000和3000上运行

我在网上找到了一小段代码,帮助我测试我的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;
我怀疑我的问题在那个白名单的某个地方,但我现在不知道它是什么


如果有人能帮助我了解发生了什么,如果他们没有答案,那可能会触发一个“啊哈”时刻。

您是否尝试过从实际的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;
}