Включить заголовок с перенаправлением

Проблема: Мое приложение HTML/JavaScript получает ошибку CORS при обработке перенаправления.

Цель: Настройте Apache для включения заголовка HTTP только во время определенного перенаправления.

Важная заметка: Этот HTML-код запускается в браузере из локально загруженного файла, а не со страницы, обслуживаемой веб-сервером.

Код:

<body>
  <div id = "response">Loading page ...</div>

<script type = "text/javascript">
  async function get_response() {
      let url = 'https://example.com/endpoint'

      fetch(url, {
        redirect: "follow"
      })
        .then(response => response.text())
        .then(data => {
          document.getElementById('response').innerHTML = data;
        })
        .catch(error => {
          console.info(error);
        });
  }

  get_response();
</script>
</body>

Описание кода:

Приведенный выше код извлекает данные из URL-адреса и отображает их в браузере. Однако веб-сайт отправляет перенаправление 302 (по дизайну). Перенаправление вызывает ошибку CORS.

Ошибка КОРС:

Access to fetch at 'https://example.com/endpoint' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Конфигурация Apache, которая генерирует перенаправление:

RewriteEngine on
RewriteRule ^(/endpoint)$ /system/endpoint.php? [END,NE,R=302]

Возможные обходные пути, которые неприемлемы:

  1. Настройте Apache для отправки заголовка CORS перед RewriteRule:

    Заголовок всегда устанавливает Access-Control-Allow-Origin "*"

Это не очень хорошее решение, потому что я не хочу отправлять этот заголовок для всех URL-адресов только для этого перенаправления. Другие страницы устанавливают этот заголовок, и когда Chrome получает несколько заголовков Access-Control-Allow-Origin с одинаковым значением, вместо принятия заголовков генерируется ошибка. Примечание. AFAIK заголовок всегда установлен требуется для включения заголовка для ответов 3xx.

  1. Измените приложение, чтобы использовать URL-адрес перенаправления вместо URL-адреса, который перенаправляет.

Это не сработает, так как конечный URL-адрес можно настроить, и цель состоит в том, чтобы не изменять приложение при изменении внутренних маршрутов.

Другие обходные пути:

Я понял, написав этот вопрос и обдумав проблему, что мой RewriteRule генерирует перенаправление, которое не требуется для всех ситуаций. Для редиректа внутри того же домена достаточно переписать URL. Для перенаправления на поддомены, что мне нужно сделать, переписать URL недостаточно.

Для того же изменения URL-адреса домена это будет работать:

RewriteRule ^(/endpoint)$ /system/endpoint.php? [L]

Для истинного перенаправления мне нужен метод для условного включения заголовка CORS.

Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
1
0
32
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Решение состоит в том, чтобы объединить директиву Apache <If> с переменной сервера REQUEST_URI:

<If "%{REQUEST_URI} == '/endpoint'">
Header always set Access-Control-Allow-Origin "*"
</If>

RewriteEngine on
RewriteRule ^(/endpoint)$ https://example2.com/system/endpoint? [END,NE,R=302]

Новая конечная точка также должна быть настроена для ответа заголовком Access-Control-Allow-Origin.

Директива Apache <Если>

Переменные сервера Apache

[Обновлять]

Отвечая Access-Control-Allow-Origin "*", мое решение противоречит цели CORS, которая заключается в предотвращении несанкционированного совместного использования ресурсов. Это решение вызовет предупреждение или нарушение в аудите безопасности. Поскольку я использую подстановочные знаки только для определенных маршрутов в бэкэнде, а не для всех маршрутов, это можно объяснить/задокументировать.

Когда я исследовал эту проблему в Stack Overflow и в Интернете, в каждом ответе/статье рекомендовалось возвращать заголовок «Access-Control-Allow-Origin «*». Это неправильное решение почти всегда. Цель элемента управления безопасностью состоит в том, чтобы обеспечить его соблюдение, а не обойти его.

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