CORS, HttpOnly, CSRFCookie; Джанго; РеактJS

Я разрабатываю веб-приложение. Мой бэкэнд находится на xxx.xxx.xxx.xxx:8000, а мой интерфейс — на xxx.xxx.xxx.xxx:3000. Я использую Django и ReactJS. Я настроил свои политики CORS на серверной части, чтобы разрешить запросы только моему фронту.

Так. Всякий раз, когда мне нужно получить файлы cookie CSRF из моего бэкэнда, они приходят в ответ под Set-Cookie с флагом HttpOnly.

Мой вопрос в том, что если мы не должны извлекать файлы cookie HttpOnly с помощью JS, почему я все еще могу сделать это с моим приложением ReactJS. Однако всякий раз, когда я удаляю этот флаг, я больше не могу устанавливать или извлекать эти файлы cookie из заголовка. Что не так? Или что правильно?

Помогите мне это понять, пожалуйста.

моя настройка django CORS:

# CSRF Cookie Settings
CSRF_COOKIE_AGE: Optional[int] = None

CSRF_TRUSTED_ORIGINS = [
    'http://localhost:3000',
    'http://xxxx.xxxx.xxxx.xxxx:3000'
]

CSRF_COOKIE_HTTPONLY = True

# CORS(cross origin resource sharing) settings
CORS_ORIGIN_ALLOW_ALL = False

CORS_ALLOW_CREDENTIALS = True

CORS_ALLOWED_ORIGINS = [
    'http://localhost:3000',
    'http://xxxx.xxxx.xxxx.xxxx:3000',
]

CORS_ALLOW_METHODS = [
'DELETE',
'GET',
'PATCH',
'POST',
'PUT',
]


мой запрос реакции:

fetch("http://xxxx.xxxx.xxxx.xxxx:8000/get_csrf",{
      method: 'GET',
      mode: 'cors',
      credentials:'same-origin',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      }
    })
      .then(response => {
        console.info(...response.headers)
        response.json()
      })
      .then(
        (result) => {
          console.info(this.getCookie('csrftoken'))
        },

        (error) => {

        }
      )

Вы говорите this.getCookie('csrftoken'), что в вашем коде должно означать window.getCookie('csrftoken')? Вы не получаете файлы cookie из ответа, который вы получаете из своего собственного интерфейса. Также у вас credentials установлено на same-origin? Это не будет работать с запросами CORS...

Abdul Aziz Barkat 22.07.2022 06:38

вы правы насчет куки. Но если я устанавливаю для файлов cookie какое-то другое значение, оно не работает и говорит, что сервер не разрешает запросы из этого источника, хотя я установил его там.

nikita_trifan 22.07.2022 07:06

Вы не добавили OPTIONS к CORS_ALLOW_METHODS, когда делается POST или другой запрос, который изменяет данные, обычно выполняется предварительный запрос с использованием метода OPTIONS. Если OPTIONS не разрешено, CORS не будет работать в этом случае...

Abdul Aziz Barkat 22.07.2022 07:26

Да, ты прав. Теперь я получаю файлы cookie, настроенные в браузере. Однако я больше не могу извлекать их с помощью JS. Мне нужно включить их в заголовок X-CSRFToken, чтобы использовать другие конечные точки.

nikita_trifan 22.07.2022 07:51

Извините, что слишком беспокою вас этим, но теперь я включил OPTIONS и credentials:'include' в заголовки запросов на выборку. Несмотря на то, что браузер устанавливает файлы cookie, я не могу извлечь их, чтобы использовать их в заголовке X-CSRFToken позже. Что я должен делать?

nikita_trifan 22.07.2022 08:07

Ваш URL-адрес имеет форму /get_csrf обычно такой URL-адрес подразумевает, что сервер вернет токен CSRF в тело ответа как JSON или как бы вы его ни реализовали, почему вы не получаете его оттуда?

Abdul Aziz Barkat 22.07.2022 10:00

@AbdulAzizBarkat Нет, OPTIONS не нужно указывать в заголовке Access-Control-Allow-Methods ответа на предварительную проверку, чтобы предварительная проверка прошла успешно.

jub0bs 22.07.2022 10:12

@ jub0bs теперь, когда я смотрю на этот вопрос, становится понятно, что он не понадобится.

Abdul Aziz Barkat 22.07.2022 10:20

Я удалил метод OPTIONS оттуда. Благодарю вас!

nikita_trifan 22.07.2022 17:14
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
9
302
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

TL;DR

Вы не можете.

Подробнее

My backend is on xxxx.xxxx.xxxx.xxxx:8000 and my frontend is on xxxx.xxxx.xxxx.xxxx:3000.

Обратите внимание, что ваш запрос — перекрестное происхождение.

Имейте в виду, что Получить стандартный (де-факто спецификация CORS) классифицирует Set-Cookie как запрещенное имя заголовка ответа. Поэтому, независимо от конфигурации CORS сервера, браузеры не позволяют клиента считывают такие заголовки из ответа на запрос из другого источника.

Веб-документы MDN о заголовке ответа Set-Cookie, который может быть неавторитетным источником правды, но его легче читать, чем стандарт Fetch, содержит следующее разъясняющее предупреждение:

Browsers block frontend JavaScript code from accessing the Set-Cookie header, as required by the Fetch spec, which defines Set-Cookie as a forbidden response-header name that must be filtered out from any response exposed to frontend code.

Ответ принят как подходящий

Итак, я собрал немного больше информации и узнал, как правильно его настроить.

  1. Да, мы не можем получить доступ к HttpOnly файлам cookie.
  2. Необходимо иметь credentials:'include' в JS-запросе на выборку.
  3. Необходимо иметь mode: 'cors' в JS-запросе на выборку.
  4. В Джанго settings.py:
CORS_ORIGIN_ALLOW_ALL = False

CORS_ALLOW_CREDENTIALS = True

CORS_ALLOWED_ORIGINS = [
    'http://localhost:3000',
    'http://xxx.xxx.xxx.xxx:3000',
]

CORS_ALLOW_METHODS = [
    'DELETE',
    'GET',
    'PATCH',
    'POST',
    'PUT',
]

CORS_EXPOSE_HEADERS = [
    'Date'
]

Другие вопросы по теме