简体   繁体   中英

Django React CSRF Issues

Building my first app using Django as back end and React as front end.

Locally, I have both running on port 8000 and 3000 respectively.

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:

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

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.

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

Django's debug reason is that "CSRF cookie not set".

However, in the console, I can see the headers are indeed sending the 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:

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.

Have you tried getting the CSRF token from the actual cookie rather than making a request to the server? Because really what you are doing now is getting the CSRF token every time you are trying to fetch anything.

Try something like the following in your 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(可能导致失去你的会话/被注销等...)。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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