Django React Проблемы CSRF - PullRequest
       48

Django React Проблемы CSRF

0 голосов
/ 05 января 2019

Создание моего первого приложения с использованием 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;

РЕДАКТИРОВАТЬ, чтобы уточнить: удаленный запрос GET проходит, только POST терпит неудачу

Когда я запускаю этот код локально, я получаю правильный ответ: «KO» меняется на «ОК», когда ответы возвращаются действительными.

Это работает только с моей машины. Если я пытаюсь получить доступ к нему с любого другого компьютера в моей сети, я получаю следующую ошибку:

403 Запрещено

Причина отладки Django заключается в том, что "файл cookie CSRF не установлен".

Однако в консоли я вижу, что заголовки действительно отправляют X-CSRFToken.

У меня есть «живая» версия моего бэкэнда, которую я также пытался использовать с теми же результатами, что и локально.

Я получу успешный тест, только если попробую его со своего компьютера, на котором установлены оба сервера разработки.

Настройки Django:

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

Я подозреваю, что моя проблема где-то в этом белом списке, но сейчас я не могу найти, что это такое.

Если кто-то может помочь мне понять, что происходит, если у него нет ответа, это может вызвать момент "ага".

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Помимо рекомендации @ tgdn о получении токена из файла cookie, я также рекомендовал бы проверить параметры политики SameSite для CSRF - и Session - Cookies, как установить его в Strict или Lax также будут запрещать отправку файлов cookie в запросах разных источников (что может привести к потере сеанса / выходу из системы и т. Д.).

0 голосов
/ 29 января 2019

Вы пытались получить токен CSRF из файла cookie, а не отправлять запрос на сервер? Потому что на самом деле то, что вы делаете сейчас, это получение токена 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...