Локальное приложение React, указывающее на размещенный сервер Django, CORS нет заголовка Access-Control-Allow-Origin

#python #reactjs #django #cors #django-cors-headers

#python #reactjs #джанго #корс #django-cors-headers

Вопрос:

Я запускаю локальную версию своего приложения react на localhost: 3000 и пытаюсь достичь конечных точек на сервере Django, размещенном на heroku

Ошибка, возникающая при каждом запросе axios: доступ к XMLHttpRequest заблокирован политикой CORS: заголовок ‘Access-Control-Allow-Origin’ отсутствует

Текущий settings.py для сервера Django:

 ALLOWED_HOSTS=['*']

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'corsheaders',
    'whitenoise.runserver_nostatic',
    'django.contrib.staticfiles',
    'accounts',
    'blog',
]
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.security.SecurityMiddleware',

    # Whitenoise
    'whitenoise.middleware.WhiteNoiseMiddleware',

    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    
    
    #'django.middleware.clickjacking.XFrameOptionsMiddleware',

    # Machina
    #'machina.apps.forum_permission.middleware.ForumPermissionMiddleware',
]

# CORS
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = False
 

Поскольку я разрешаю всем источникам отправлять запросы, похоже, что этот тип проблемы CORS должен быть отключен. Я попытался удалить все другое промежуточное программное обеспечение, кроме CorsMiddleware, и это ничего не изменило.

На данный момент немного озадачен, потому что моя конфигурация кажется правильной в соответствии https://github.com/adamchainz/django-cors-headers

Вот пример вызова api из моего приложения react, который вызывает заголовок «no ‘Access-Control-Allow-Origin'»

 function callCSRFApi(){
  return axios.request({
    method: 'GET',
    url: 'http://example.com/csrf/',
  });
}
 

Следует отметить, что я нажимаю конечные точки на сервере Django, даже если он не настроен как API django_rest.

Я также попытался установить пользовательское промежуточное программное обеспечение, которое всегда должно определять Access-Control-Allow-Origin, но все равно получил, что заголовок отсутствует:

 class CorsMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        if (request.method == "OPTIONS"  and "HTTP_ACCESS_CONTROL_REQUEST_METHOD" in request.META):
            response = http.HttpResponse()
            response["Content-Length"] = "0"
            response["Access-Control-Max-Age"] = 86400
        response["Access-Control-Allow-Origin"] = "*"
        response["Access-Control-Allow-Methods"] = "DELETE, GET, OPTIONS, PATCH, POST, PUT"
        response["Access-Control-Allow-Headers"] = "accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with"
        return response
 

Я думаю, что проблема может быть в том, что у нас нет сервера Django, настроенного как приложение django_rest, или что у django есть логика, по которой к нему нельзя получить доступ с локального хоста.

Примечание:

  • Я тестирую в окне инкогнито после прочтения, что у других возникли проблемы с кэшем
  • Пробовали вернуться к более ранней версии django-cors-headers
  • Пробовали без CORS_ALLOW_CREDENTIALS = False
  • Запросы GET работали при запуске как сервера django, так и приложения react на разных портах localhost
  • Python 3.7, Django 3.0.7, django-cors-заголовки 3.5.0, React 17.0.1, axios 0.21.0

Ответ №1:

Попробуйте установить CORS_ALLOW_CREDENTIALS = True в настройках Django и { withCredentials: true } в конфигурации axios.

Комментарии:

1. function callCSRFApi(){ return axios.request({ method: 'GET', url: 'http://' hostURL '/csrf/', // TODO: Will need to change to Prod withCredentials: true, }); }

2. Я установил CORS_ALLOW_CREDENTIALS = True в settings.py так же хорошо, но получая тот же результат

3. Добавлен новый ответ.

Ответ №2:

У меня самого были некоторые проблемы с axios и CSRF, и мне нравится просто использовать собственный fetch-API. Этот код работает с Django и corsheaders:

 export async function authenticateUser() {
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRFToken': Cookies.get('csrftoken')
    },
    credentials: 'include',
  });
  return response.json()
}
 

Комментарии:

1. Ошибка, похоже, другая: [Доступ к выборке в ‘ example.com/csrf ‘ из источника ‘ localhost:3000 ‘ заблокирован политикой CORS: ответ на предполетный запрос не проходит проверку контроля доступа: перенаправление не разрешено для предполетного запроса]. Но запрос по-прежнему блокируется политикой CORS.

2. Вы также установили js-cookie и включили «X-CSRFToken»? Вам также понадобится файл cookie ‘csrftoken’ в вашем приложении (например, войдя на страницу администратора).

3. На данный момент я просто делаю запрос get, поэтому я не думаю, что мне нужен токен csrf (но поправьте меня, если я ошибаюсь).

4. Следует отметить, что выполнение перекрестных запросов между localhost: 3000 и localhost: 8000 работает, но когда я пытаюсь указать localhost: 3000 (local react app) на example.com (приложение prod django) Я начинаю получать ошибки CORS.

Ответ №3:

Попробуйте добавить белый список в свой settings.py

корс

CORS_ALLOWED_ORIGINS = [ ‘http://localhost:3000 ‘, ]