Решайте междоменные проблемы с помощью Nginx
Решайте междоменные проблемы с помощью Nginx

Научите вас, как быстро и легко решать междоменные проблемы с помощью Nginx.

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

Подготовка перед анализом:

Адрес внешнего веб-сайта: http://localhost:8080.

URL-адрес сервера: http://localhost:59200.

Во-первых, убедитесь, что сервер не обрабатывает междоменные проблемы. Во-вторых, используйте почтальона, чтобы проверить, нормально ли работает интерфейс сервера.

картина
картина

Когда веб-сайт 8080 обращается к интерфейсу сервера, возникает междоменная проблема. Как ее решить? Далее я перечислил различные ситуации, возникающие в разных доменах, и решил их через прокси-сервер nginx (то же самое происходит и в фоновом режиме, если вы понимаете принцип).

Междоменный подход в основном включает в себя 4 заголовка ответа:

  • Access-Control-Allow-Origin использовать Разрешено в настройках Междоменный адрес источника запроса домена (Предполетные запросы и официальные запросы находятся на сайте Междоменный. домен будет проверяться каждый раз)
  • Access-Control-Allow-Headers Междоменный Специальные информационные поля заголовка, которые разрешено переносить по домену. (Только при предполетной проверке запроса)
  • Access-Control-Allow-Methods Междоменный разрешенные доменом методы запроса или HTTP-глаголы (Только при предполетной проверке запроса)
  • Access-Control-Allow-Credentials Междоменный разрешен? доменделатьиспользоватьcookies,Если вы хотите Междоменный Если домен использует файлы cookie, вы можете добавить этот заголовок ответа на запрос и установить значение true (установка или отключение этого параметра не повлияет на отправку запроса, а повлияет только на запрос в Междоменный Следует ли сохранять файлы cookie при поиске, но если они установлены, необходимо установить как предполетные запросы, так и формальные запросы). Но не рекомендуется домен useuse (в проекте использовался использовать, но он нестабилен и некоторые браузеры не могут его перенести) без необходимости, потому что альтернатив много.

Во многих статьях в Интернете говорится, что добавление этих заголовков ответов непосредственно в Nginx может решить междоменные проблемы. Конечно, большинство случаев можно решить, но я считаю, что есть еще много случаев, когда о междоменных проблемах все равно будут сообщать. конфигурация правильная.

Что такое предполетный запрос?:когда произойдет Междоменный доменусловное время,Браузер сначала запрашивает сервер,Находится ли доменное имя текущей веб-страницы в списке разрешений сервера.,И какие HTTP-глаголы и поля заголовка можно использовать. получить только положительный ответ,Браузер выдаст формальный запрос XMLHttpRequest.,В противном случае будет сообщено об ошибке. Как показано ниже

картина
картина

Приступаем к симуляции:

Порт прокси Nginx: 22222, конфигурация следующая

Язык кода:javascript
копировать
server {
        listen       22222;
        server_name  localhost;
        location  / {
            proxy_pass  http://localhost:59200;
        }
}

Проверьте, успешно ли работает прокси, и снова получите доступ к интерфейсу через порт прокси-сервера Nginx 2222. Вы можете видеть, что доступ к интерфейсу возможен в обычном режиме после передачи прокси, как показано ниже.

картина
картина

Затем используйте веб-сайт 8080 для доступа к адресу интерфейса прокси-сервера Nginx. Сообщение об ошибке выглядит следующим образом: ↓↓↓.

Случай 1

“ Access to XMLHttpRequest at ‘http://localhost:22222/api/Login/TestGet’ from origin ‘http://localhost:8080’ 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.

картина
картина

Ошибку можно четко определить по сообщению об ошибке (обратите внимание на красную часть). Описание priflight — это предварительный запрос. Междоменный механизм CORS сначала выполнит предполетный запрос (запрос OPTIONS), а затем реальный запрос. быть отправлено после успешного выполнения запроса. Это сделано для того, чтобы серверы знали о стандарте CORS и защищали старые серверы, которые не поддерживают CORS.

Из сообщения об ошибке мы можем обнаружить, что в заголовке ответа на предварительный запрос отсутствует Access-Control-Allow-Origin. Мы можем просто изменить его, если он неправильный. Измените информацию о конфигурации Nginx следующим образом (красная часть — добавленная часть), заполните все недостающее, это очень просто и понятно.

Язык кода:javascript
копировать
server {
        listen       22222;
        server_name  localhost;
        location  / {
           add_header Access-Control-Allow-Origin 'http://localhost:8080';
           proxy_pass  http://localhost:59200; 
        }
    }

Ха-ха, когда я был полон радости и думал, что смогу решить эту проблему, я обнаружил, что все еще сообщаю о той же проблеме.

картина
картина

Однако в нашей конфигурации все в порядке. Проблема связана с Nginx. Ссылка ниже: http://nginx.org/en/docs/http/ngx_http_headers_module.html.

картина
картина

Директива add_header используется для добавления поля возвращаемого заголовка, которое действительно тогда и только тогда, когда коды состояния соответствуют указанным на рисунке. Если вы хотите, чтобы каждое ответное сообщение содержало информацию о поле заголовка, вам необходимо добавить всегда в конце (после моего тестирования только информацию заголовка Access-Control-Allow-Origin необходимо добавлять с помощью Always, а другая информация заголовка будет переносим обратно без добавления всегда), тогда попробуем

Язык кода:javascript
копировать
server {
        listen       22222;
        server_name  localhost;
        location  / {
           add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
           proxy_pass  http://localhost:59200; 
        }
    }

После изменения конфигурации я обнаружил, что она вступила в силу. Конечно, это не междоменная проблема. Вышеупомянутая проблема была решена, поскольку содержание ошибки изменилось.

Случай 2

“ Access to XMLHttpRequest at ‘http://localhost:22222/api/Login/TestGet’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.

картина
картина

Из сообщения об ошибке можно узнать, что предварительный запрос (запрос опции), который является поведением междоменного браузера по умолчанию, не получает код состояния ok. В это время файл конфигурации изменяется при запросе. запрос опции, код состояния возвращается в браузер (обычно 204).

Язык кода:javascript
копировать
 server {
        listen       22222;
        server_name  localhost;
        location  / {
           add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
           if ($request_method = 'OPTIONS') {
                return 204;
           }
           proxy_pass  http://localhost:59200; 
        }
    }

После завершения настройки я обнаружил, что сообщение об ошибке изменилось.

Случай 3

“ Access to XMLHttpRequest at ‘http://localhost:22222/api/Login/TestGet’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

картина
картина

Это означает, что авторизация информации заголовка отсутствует в заголовке ответа предварительного запроса Access-Control-Allow-Headers (различные ситуации будут разными. После возникновения междоменного доступа добавленная информация пользовательского заголовка не разрешена, и ее необходимо добавить в заголовок ответа на запрос. Контроль доступа. -Allow-Headers, чтобы браузер знал, что перенос этой информации заголовка распознается сервером как законный. Здесь я несу авторизацию, а остальные могут быть токенами. Я знаю проблему и). затем измените его, добавьте соответствующие недостающие части и повторите попытку.

Язык кода:javascript
копировать
server {
        listen       22222;
        server_name  localhost;
        location  / {
           add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
           if ($request_method = 'OPTIONS') {
               add_header Access-Control-Allow-Headers 'authorization'; #Почему это написано внутри, если вместо Access-Control-Allow-Origin? Потому что здесь будут проверяться только предполетные запросы
               return 204; 
          } 
        proxy_pass http://localhost:59200; 
    }
}

В это время было обнаружено, что проблема с отчетами об ошибках вернулась к ситуации 1.

картина
картина

Тестирование подтвердило, что пока в if ($request_method = ‘OPTIONS’) записан add_header, внешняя конфигурация будет недействительной при выполнении предполетного запроса. Почему? ↓↓.

В официальной документации сказано следующее:

“ There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.

Это означает, что если на текущем уровне нет инструкции add_header, наследуется add_header предыдущего уровня. Напротив, если текущий уровень имеет add_header, он не должен иметь возможности наследовать add_header предыдущего уровня.

картина
картина

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

Язык кода:javascript
копировать
server {
        listen       22222;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080';
                add_header Access-Control-Allow-Headers 'authorization';
                return 204;
            }
            proxy_pass  http://localhost:59200; 
        }
    }

На этот раз, после модификации, я обнаружил, что междоменная проблема решена.

картина
картина

Однако, хотя вышеизложенное решает междоменную проблему, учитывая, что версия Nginx может быть обновлена ​​в будущем, я не знаю, будет ли это правило изменено, учитывая, что этот метод записи может содержать два Access-Control-Allow-. Происхождение тоже имеет место. Не допускается, как описано ниже. Поэтому конфигурацию следует изменить следующим образом:

Язык кода:javascript
копировать
server {
        listen       22222;
        server_name  localhost;
        location  / {
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080';
                add_header Access-Control-Allow-Headers 'authorization';
                return 204;
            }
            if ($request_method != 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
            }
            proxy_pass  http://localhost:59200; 
        }
    }

Это еще не конец, продолжайте общаться ↓↓

Случай 4

Более ранние API могут использовать только запросы POST и GET, а заголовок ответа на запрос Access-Control-Allow-Methods по умолчанию поддерживает только POST и GET между доменами. При возникновении других типов запросов также возникают междоменные исключения.

Например, я изменил запрошенный метод запроса интерфейса API с исходного GET на PUT и попробовал еще раз. На консоли будет выдана ошибка:

“ Access to XMLHttpRequest at ‘http://localhost:22222/api/Login/TestGet’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.

картина
картина

Содержание ошибки также очень ясно. В этом предварительном запросе метод PUT не разрешен для использования в междоменном режиме. Нам нужно изменить конфигурацию Access-Control-Allow-Methods (если что-то отсутствует, я могу это сделать). просто добавим его сюда. После PUT вы можете добавить его самостоятельно), чтобы браузер знал, что сервер разрешен.

Язык кода:javascript
копировать
server {
  listen 22222;
  server_name localhost;
  location / {
    if ($request_method = 'OPTIONS') {
      add_header Access-Control-Allow-Origin 'http://localhost:8080';
      add_header Access-Control-Allow-Headers 'content-type,authorization';
      add_header Access-Control-Allow-Methods 'PUT';# Почему он добавляется только к этому if, а не к следующему if? Поскольку здесь будет проверяться только предполетный запрос, то, конечно, ничего страшного, если вы его добавите.
      return 204;
    }
    if ($request_method != 'OPTIONS') {
      add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
    }
    proxy_pass http://localhost:59200;
  }
}

Обратите внимание, что после изменения типа PUT заголовок ответа запроса Access-Control-Allow-Headers автоматически проверит заголовок запроса типа контента, что аналогично случаю 3. Просто восполните все пропущенное. Если тип контента не добавлен, будет сообщено о следующей ошибке. (Для простоты: Access-Control-Allow-Headers и Access-Control-Allow-Methods можно установить в *, что означает, что все они совпадают. Однако не рекомендуется устанавливать Access-Control-Allow-Origin в * . Из соображений безопасности ограничения Доменное имя очень необходимо.

картина
картина

После добавления их всех проблема решена. Сообщаемая здесь ошибка 405 заключается в том, что интерфейс на моем сервере открывает только GET и не открывает PUT. В этот момент я использую метод PUT для запроса этого интерфейса, поэтому интерфейс вернет это. код состояния.

картина
картина

Случай 5

Наконец, позвольте мне поговорить о другой ситуации, то есть серверная часть обрабатывает междоменный доступ, и нет необходимости решать эту проблему самостоятельно (вот жалоба, некоторые серверные инженеры меняют код сервера для решения кросс-доменной проблемы). домен, но они не понимают принцип, поэтому могут найти его в Интернете. Фрагмент кода вставлен, что приводит к неполной обработке информации ответа, например. Метод не добавляется полностью, заголовки не добавляются в точку, тот, который вы используете, может не содержать тех, которые используются в реальном проекте, код статуса возврата запроса опций не добавляется и т. д., в результате чего Nginx использует общий конфигурации и может сообщать о следующих аномальных явлениях)

“ Access to XMLHttpRequest at ‘http://localhost:22222/api/Login/TestGet’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: The ‘Access-Control-Allow-Origin’ header contains multiple values ‘*, http://localhost:8080’, but only one is allowed.

картина
картина
картина
картина

Это означает, что в этот момент возвращается несколько заголовков ответа на запрос Access-Control-Allow-Origin, но разрешен только один. В этом случае, конечно, вы можете изменить конфигурацию и удалить конфигурацию Access-Control-Allow-Origin. Однако при возникновении такой ситуации рекомендуется выбрать только одну из конфигураций Nginx и разрешения междоменных проблем на стороне сервера. (Обратите внимание, что если вы будете следовать моему методу написания выше, если $request_method = ‘OPTIONS’ Access-Control-Allow-Origin в этом случае не может быть удален. Просто удалите тот, который находится в !='OPTIONS', потому что, если это предполетный запрос, он будет возвращен напрямую, и запрос не будет перенаправлен на номер 5920. 0, если его тоже удалить, будет сообщаться о той же ошибке, что и в случае 1. Так почему же вы говорите, что междоменная проблема должна решаться на уровне кода сервера или с помощью прокси Nginx? это вверх, иначе люди, которые не понимают принцип, возможно, вы не сможете решить проблему, если найдете кусок кода, размещенный в Интернете)

Снова опубликуйте полную конфигурацию (заполните * в соответствии с вашими «предпочтениями»):

Язык кода:javascript
копировать
server {
        listen       22222;
        server_name  localhost;
        location  / {
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080';
                add_header Access-Control-Allow-Headers '*';
                add_header Access-Control-Allow-Methods '*';
                add_header Access-Control-Allow-Credentials 'true';
                return 204;
            }
            if ($request_method != 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
                add_header Access-Control-Allow-Credentials 'true';
            }
            proxy_pass  http://localhost:59200; 
        }
    }

или:

Язык кода:javascript
копировать
server {
        listen       22222;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
            add_header Access-Control-Allow-Headers '*';
            add_header Access-Control-Allow-Methods '*';
            add_header Access-Control-Allow-Credentials 'true';
            if ($request_method = 'OPTIONS') {
                return 204;
            }
            proxy_pass  http://localhost:59200; 
        }
    }

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

Подвести итог

Если эта статья оказалась для вас полезной или вдохновляющей, нажмите трижды: «Нравится», «Переслать» и прочитайте. Ваша поддержка — моя самая большая мотивация продолжать писать.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose