Подробное объяснение междоменных проблем в веб-разработке

Ajax

Эта статья была опубликована сообществом cloud+community

Студенты, которые занимались веб-разработкой, должны были столкнуться с междоменными проблемами.Когда мы отправляем Ajax-запрос с одного доменного имени на другое доменное имя, при открытии консоли браузера мы увидим междоменную ошибку.Сегодня мы поговорим об этом. , Расскажите о междоменных проблемах.

1. Политика одинакового происхождения браузера

Определение гомологии таково: если ***протокол*** из двух страниц,* порт* (если указано) и *** доменное имяодинаковые, две страницы одинаковыеисточник*. Политика того же источника ограничивает взаимодействие документов или сценариев, загруженных из одного источника, с ресурсами из другого источника. Это важный механизм безопасности для изоляции потенциально вредоносных файлов.

2. Причины междоменных сообщений об ошибках

Чтобы проиллюстрировать проблему, мы можем провести следующие эксперименты: мы настраиваем среду разработки локально, а клиентhttp://localhost:3001на серверhttp://localhost:3000Отправьте два запроса, один использует javascript для асинхронного запроса данных, а другой использует тег img для запроса данных.После того, как сервер получит запрос, он распечатает журнал полученного запроса, как показано на следующем рисунке:

img
Клиент отправляет два запроса

img
Сервер печатает лог и обрабатывает запрос

Откройте консоль клиентского браузера, вы увидите, что было сделано два запроса, и на оба получен ответ с кодом состояния 200. При этом консоль сообщила об ошибке, то есть запрос xhr сообщил об ошибке. Из этого мы можем узнать, что сообщение о междоменной ошибке генерируется по следующим трем причинам:

  • Ограничения на стороне браузера (сервер получает запрос и корректно возвращает его)
  • Отправляется запрос XMLHttpRequest (запрос, отправленный с использованием тега img, имеет тип json и не сообщит об ошибке)
  • Запрашиваемые ресурсы из разных доменов

Только при одновременном выполнении этих трех условий браузер выдаст междоменную ошибку.

3. Идея решения кроссдоменности

Теперь, когда мы знаем причину междоменной ошибки, решение очень интуитивно понятно. Мы можем соответственно разобраться с тремя причинами ошибки. Соответствующее решение также имеет три направления:

  • Преодолейте ограничения браузера
  • Не отправлять запросы XHR
  • разрешать междоменные

Они будут объяснены отдельно ниже.

3.1 Преодолеть ограничения браузера

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

Возьмем в качестве примера браузер Chrome под MacOS, используем команду в терминале

open -n /Applications/Google\ Chrome.app/ --args --disable-web-security  --user-data-dir=/Users/your-computer-account/MyChromeDevUserData/

Откройте браузер, вы можете отключить функцию проверки безопасности браузера Chrome, а также отключить функцию проверки междоменной безопасности, поэтому повторите предыдущий пример для проверки и обнаружите, что в это время не будет сообщено об ошибке, и вы также может заставить сервер правильно возвращать данные.

img
Отключить проверку безопасности браузера

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

3.2 JSONP реализует кроссдоменность

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

JSONP,是 JSON with Padding 的简称,它是 json 的一种补充使用方式,利用 script 标签来解决跨域问题。JSONP 是非官方协议,他只是前后端一个约定,如果请求参数带有约定的参数,则后台返回 javascript 代码而非 json 数据,返回代码是函数调用形式,函数名即约定值,函数参数即要返回的数据。

Принцип реализации JSONP показан на следующем рисунке:

img
Принцип реализации JSONP

Сначала определите функцию в js на стороне клиента (при условии, что имя - обработчик), затем динамически создайте тег скрипта и вставьте его на страницу.Атрибут src тега скрипта - это адрес, который нужно вызвать, и в то же время , добавьте контракт на стороне сервера к параметру вызывающего URL-адреса (при условии, что имя является обратным вызовом, а значением параметра является определенный обработчик имени функции), сервер получает запрос, и если он обнаруживает, что запрошенный URL-адрес содержит согласованные параметры, он возвращает код javascript в виде вызова функции.Имя функции — это обработчик значения параметра обратного вызова, а параметр функции — возвращаемые данные. Таким образом, после того, как клиент получит возвращенный результат, он выполнит функцию обработчика для обработки возвращенных данных.

Мы используем jquery для отправки запроса в формате JSONP на сервер, и запрос и соответствующий ответ можно увидеть из консоли браузера, как показано на следующем рисунке:

img
JSONP-запрос

img
Ответ на запрос JSONP

Как видно из приведенного выше рисунка, при отправке запроса JSONP тип запроса является типом сценария, а не типом xhr, что нарушает три необходимых условия для отчета о междоменных ошибках, не генерирует междоменные ошибки и также проверяет, возвращает ли сервер данные в формате вызова кода javascript, среди которых Jquery331045** Эта длинная строка имен функций автоматически генерируется jquery.

Поскольку принцип JSONP заключается в использовании тегов сценария для загрузки данных, его совместимость очень хорошая, но использование JSONP для решения междоменных проблем имеет следующие недостатки:

  1. Можно отправлять только GET-запросы
  2. Запрос XHR не отправлен, поэтому многие события в запросе XHR не могут быть обработаны.
  3. сервер надо менять

3.3 Совместное использование ресурсов CORS между источниками

CORS — это стандарт W3C, полное название — «Совместное использование ресурсов кросс-происхождения» (Cross-origin resource sharing). Это позволяет браузерам выполнять запросы XMLHttpRequest к серверам из разных источников, тем самым преодолевая ограничение, заключающееся в том, что AJAX можно использовать только с одним и тем же источником. CORS основан на положениях протокола http о междоменных аспектах.При использовании клиентский браузер напрямую асинхронно запрашивает вызываемый сервер и добавляет поле ответа в заголовок ответа, чтобы указать браузеру разрешить междоменное взаимодействие. фон.

img
междоменная ошибка

Возвращаясь к сообщению о междоменной ошибке в начале статьи, вы можете видеть, что конкретная информация об ошибке: сервер не устанавливает заголовок ответа Access-Control-Allow-Origin, что приводит к тому, что ошибка Установив Access-Control-Allow-Origin: * этот заголовок ответа, мы сможем решить проблему. Однако достаточно ли этой настройки для всех ситуаций? Идем дальше: как браузер проверяет междоменные ошибки при использовании CORS? Как мы упоминали ранее, несмотря на то, что браузер сообщает об ошибке, сервер перед этим принял запрос Итак, всегда ли браузер делает запрос, прежде чем принять решение? Давайте обсудим их один за другим.

3.3.1 Как браузеры проверяют междоменные ошибки

Основной принцип, по которому браузеры проверяют междоменные ошибки:

浏览器检测到 ajax 请求的域与当前域不一致,会在请求头中增加 Origin 字段,然后检查服务端响应头 Access-Control-Allow-Origin,如果不存在或不匹配,则报跨域错误。

img
Принцип проверки браузера на междоменные ошибки

3.3.2 Всегда ли браузер сначала делает запрос, а затем оценивает его на основе заголовка ответа Access-Control-Allow-Origin?

Ответ таков: для простого запроса есть, а для сложного запроса — нет. При непростом запросе браузер напрямую не запрашивает требуемые ресурсы, а сначала выдает предварительный запрос, после того как запрос путем предварительной проверки потребует запроса ресурсов.

img
Непростой запрос на предварительную проверку

Здесь задействована концепция простого запроса и непростого запроса, так в чем же разница между простым запросом и непростым запросом? MDN определяет непростой запрос, если выполняется одно из следующих условий, это непростой запрос:

  1. Использовались следующие методы HTTP: PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH.
  2. Используемые заголовки, отличные от: Accept, Accept-Language, Content-Language, Content-Type
  3. Значение заголовка Content-Type не является одним из следующих: application/x-www-form-urlencoded, multipart/form-data, text/plain
  4. Объект XMLHttpRequestUpload в запросе имеет любое количество зарегистрированных прослушивателей событий.
  5. В запросе использовался объект ReadableStream.

Просто, помимо привычного нам использования методов get и post, а также наиболее часто используемых Accept, Accept-language, Content-Language и Types for Application/X-WWW-FORM-URLENCODED, MULTIPART/FORM-DATA, Заголовок запроса Content-Type TEXT / Plain, другие в основном непростые запросы. Для этих непростых запросов браузер выдает два запроса, первый раз, чтобы удовлетворить запрос, удовлетворить запрос на проверку ответа, выдаст запрос на ресурс.

img
не простой процесс запроса

В производственной среде, если необходимо отправить не простой междоменный запрос, время ответа будет увеличиваться на два запроса каждый раз, для этого в заголовке ответа добавляется параметр Access-Control-Max-Age. Стандарт W3C Время кеша браузера для предварительного запроса непростого запроса.В течение срока действия кеша непростой запрос может не отправлять предварительный запрос.Кроме того, в фактической разработке вы можете установить полученный метод запроса на сервере в OPTIONS и вернуть его напрямую .200, что также ускоряет ответ.

3.3.3 Можно ли установить Access-Control-Allow-Origin: *

img
междоменный с куки

Когда нам нужно отправить запрос с куки, если Access-Control-Allow-Origin напрямую установлен в подстановочный знак *, он не может пройти проверку браузера.В это время значение заголовка ответа должно точно соответствовать домену запроса Кроме того, вам также необходимо установить значение заголовка ответа Access-Control-Allow-Credentials в значение true, указывающее, что междоменные запросы с файлами cookie поддерживаются.

3.3.4 Сводка заголовков запросов CORS и заголовков ответов

Заголовок запроса:

  • Происхождение: этот заголовок добавляется перед отправкой браузером междоменного запроса Ajax, а значением является домен, отправивший запрос.
  • Access-Control-Request-Method: если используется метод, отличный от методов запроса GET и POST, браузер добавит этот заголовок со значением текущего метода запроса.
  • Access-Control-Request-Headers: используются пользовательские заголовки или заголовки, отличные от Accept, Accept-Language, Content-Language и Content-Type, браузер добавит этот заголовок, а значение — текущий метод запроса.

Заголовок ответа:

  • Access-Control-Allow-Origin: указывает, какие домены разрешены сервером для запроса ресурсов.
  • Access-Control-Allow-Methods: когда клиент включает заголовок запроса Access-Control-Request-Method, сервер должен ответить на заголовок. Значение обычно получается из Access-Control-Request-Method в заголовке Reauest. .
  • Access-Control-Allow-Headers: когда клиент включает заголовок запроса Access-Control-Request-Headers, сервер должен ответить на заголовок. Значение обычно получается из заголовков Access-Control-Request-Headers в заголовке Реюст
  • Access-Control-Expose-Headers: укажите, какие заголовки ответа клиент может получить с помощью метода getResponseHeaders объекта XHR.
  • Access-Control-Allow-Credentials: разрешить перекрестные запросы с файлами cookie.
  • Access-Control-Max-Age: время кэширования предварительных запросов.

4. Резюме

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

Эта статья была разрешена автором для публикации сообщества Tencent Cloud + на различных каналах.

Найдите и подпишитесь на общедоступную учетную запись «Сообщество Yunjia», получите технические галантереи как можно скорее и ответьте на 1024 после подписки, чтобы отправить вам подарочный пакет технических курсов!