Конфигурация django-cors-headers и nginx: в ответе перед проверкой отсутствуют заголовки CORS - PullRequest
0 голосов
/ 25 октября 2019

Я использую django-cors-headers 3.1.1 для обработки запросов и ответов между моими приложениями Django-backend и Javascript-frontend. Транспорт не защищен (т. Е. Http, а не https).

При локальном размещении все работает нормально. Но после развертывания на сервере я перестал видеть заголовки CORS.

Вот заголовки в разработке: enter image description here и в производстве: enter image description here

Сообщение об ошибке:

Access to XMLHttpRequest at 'http://[HOST_IP]/api/assets/' from origin 'http://my_custom_domain.eu' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Мои конфигурации nginx выглядят следующим образом:

server {
    listen 80;
    server_name [HOST_IP];

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/ubuntu/[path_to_app]/app.sock;

        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Max-Age' 86400;

        if ($request_method = 'OPTIONS') {
            add_header 'Content-Type' 'text/html; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
        }
        if ($request_method = 'PUT') {
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
        }
        if ($request_method = 'GET') {
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
        }
    }

    location /static/ {
        autoindex on;
        alias /home/ubuntu/[path_to_app]/site/static/;
    }
}

Настройки django-cors-headers теперь идентичны в разработке и в производстве:

INSTALLED_APPS = (
    …
    "corsheaders",
    …
)
MIDDLEWARE = [
    …
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    …
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = ['DELETE','GET','OPTIONS','PATCH','POST','PUT']

На стороне клиента я пытался добавить заголовок '' Access-Control-Request-Method ':' PUT ', но браузер отклонил это. В вызове клиента отмечается необычное:

  axios({
    method: 'put',
    url: `${this.backendUrl}/api/assets/`,
    data: formData,
    headers: {
      'Content-Type': 'application/octet-stream',
    }
  })

Кроме того, я впервые пытаюсь разместить на Amazon AWS EC2, поэтому, возможно, есть какая-то необходимая конфигурация AWS, о которой я не знаю. Например, необходимо ли включать CORS с использованием API-шлюза? Документация не говорит об этом («Если вы используете API-интерфейс импорта шлюза API, вы можете настроить поддержку CORS с помощью файла OpenAPI»).

Приложение внешнего интерфейса размещается наВедро S3 со следующей политикой CORS:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

Что мне здесь не хватает? Есть ли какая-то необходимая конфигурация на стороне сервера (особенно nginx)?

Некоторые другие решения, которые я пробовал:

У меня есть сомнения, является ли источник запроса / ответа правильным (например, переменная APPEND_SLASH),Но если дело обстоит так, разве не должна возникать ошибка при локальном размещении?

Я также пытался установить заголовки прокси, как в этот вопрос , но, не зная nginx, он был обречен. потерпеть неудачу.

1 Ответ

0 голосов
/ 27 октября 2019

Мне удалось решить эту проблему, изменив 3 вещи:

AWS

Я заметил, что Документация AWS гласит:

CORSуже включен для API Amazon EC2 и готов к использованию. Вам не нужно выполнять никаких дополнительных действий по настройке, чтобы начать использовать эту функцию. Нет никаких изменений в способе совершения звонков в API Amazon EC2;они все еще должны быть подписаны действительными учетными данными AWS, чтобы гарантировать, что AWS может аутентифицировать запрашивающую сторону. […]

Обычно это обрабатывается AWS SDK или CLI, но в моем случае я не использовал ни один из них, поэтому мне пришлось добавить AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY. В моем случае я просто использовал библиотеку aws4 :

  axios(aws4.sign({
    accessKeyId: this.awsAccessKey,
    secretAccessKey: this.awsSecretAccessKey,
    method: 'put',
    url: `${this.backendUrl}/api/assets/`,
    data: formData,
    body: JSON.stringify(formData),
    service: 'ec2',
    region: 'eu-central-1',
    path: '/',
    headers: {
      'Content-Type': 'application/octet-stream'
    }
  }))

Я видел множество примеров того, как добавить AWS Signature v.4 без каких-либо дополнительных зависимостей.

NGINX

В конфигурации nginx я поместил все операторы add_headers в условные кодовые блоки. Идея пришла из этого поста .

server {
    listen 80;
    server_name [HOST_IP];

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/ubuntu/[path_to_app]/app.sock;


        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
            add_header 'Access-Control-Max-Age' 86400;
            add_header 'Content-Type' 'text/html; charset=utf-8';
            add_header 'Content-Length' 0;
            return 204;
        }
        if ($request_method = 'PUT') {
            add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
        }
        if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
            add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
        }
    }

    location /static/ {
        autoindex on;
        alias /home/ubuntu/analizy/be/site/static/;
    }
}

Django-cors-header

Здесь достаточно добавить заголовки не по умолчанию.

from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = list(default_headers) + [
    'X-Amz-Date',
]

Надеюсь, что это кому-нибудь поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...