简体   繁体   English

Django React CSRF问题

[英]Django React CSRF Issues

Building my first app using Django as back end and React as front end. 使用Django作为后端和React作为前端构建我的第一个应用程序。

Locally, I have both running on port 8000 and 3000 respectively. 在本地,我分别在端口8000和3000上运行。

I have a short snippet of code I found online to help me test whether or not my CSRF and CORS policies are set correctly: 我在网上找到了一小段代码,以帮助我测试我的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;

EDIT to clarify: Remote GET request passes, only POST fails 编辑澄清:远程GET请求通过,只有POST失败

When I run this code locally, I get the correct response which is, the "KO" gets changed to "OK" when the responses come back valid. 当我在本地运行此代码时,我得到正确的响应,即当响应返回有效时,“KO”变为“OK”。

This only works from my machine. 这只适用于我的机器。 If I try to access it from any other machine in my network, I get the following error: 如果我尝试从网络中的任何其他计算机访问它,我会收到以下错误:

403 Forbidden 403禁止

Django's debug reason is that "CSRF cookie not set". Django的调试原因是“CSRF cookie未设置”。

However, in the console, I can see the headers are indeed sending the X-CSRFToken. 但是,在控制台中,我可以看到标题确实正在发送X-CSRFToken。

I have a "live" version of my backend that I've also tried to tap into with same results as locally. 我有一个我的后端的“实时”版本,我也尝试使用与本地相同的结果。

I only get a successful test if I try it from my own computer, where both dev servers sit. 如果我从我自己的计算机上尝试它,我只能得到一个成功的测试。

Django settings: Django设置:

CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = ['localhost:3000', 'My_Public_Ip:3000']

I suspect my issue is somewhere in that whitelist but I'm at a loss at this point to find what it is. 我怀疑我的问题是在白名单中的某个地方,但我现在不知道发现它是什么。

If someone could help me understand what's happening, if they don't have an answer, that might trigger an "aha" moment. 如果有人可以帮我理解发生的事情,如果他们没有答案,那可能会引发“aha”时刻。

Have you tried getting the CSRF token from the actual cookie rather than making a request to the server? 您是否尝试从实际cookie中获取CSRF令牌而不是向服务器发出请求? Because really what you are doing now is getting the CSRF token every time you are trying to fetch anything. 因为您现在正在做的是每次尝试获取任何内容时都获取CSRF令牌。

Try something like the following in your JavaScript: 在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中获取令牌之外,我还建议检查CSRF的 会话和Cookie的SameSite策略设置,因为将其设置为StrictLax也会禁止在跨域请求中发送cookie(可能导致失去你的会话/被注销等...)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM