Кросс-домен Ajax, это должно быть наиболее полное решение

JavaScript браузер Ajax

предисловие

С первого контакта с фронтенд-разработкой,跨域Это слово повторяется с высокой частотой.До сих пор я отлаживал N междоменных проблем, и я также составил соответствующую статью за 16 лет, но я все еще чувствую, что чего-то не хватает, поэтому сейчас реорганизован.

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

Контур

Что касается междоменного доступа, существует N типов, эта статья посвящена толькоajax请求跨域(Кросс-доменный Ajax является лишь частью «политики одного и того же происхождения» браузера, другие включают междоменный междоменный Cookie, междоменный iframe, междоменный LocalStorage и т. д., которые здесь не представлены), содержание примерно такое же, как следует:

  • что такое перекрестный домен ajax

    • принцип
    • Производительность (разобрались с некоторыми возникшими проблемами и решениями)
  • Как решить междоменный ajax

    • JSONP-метод
    • CORS-метод
    • метод прокси-запроса
  • Как анализировать междоменный ajax

    • Анализ захвата http пакетов
    • Некоторые примеры

что такое перекрестный домен ajax

Принцип кроссдоменности ajax

У Ajax есть проблема с междоменной ошибкой запроса, основная причина в том, что браузер использует «политику одного и того же происхождения», вы можете обратиться к

Политика одинакового происхождения в браузере и как этого избежать (Ифэн Жуан)

Принцип запроса CORS

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 Это позволяет браузерам отправлять запросы XMLHttpRequest к серверам с разными источниками, тем самым преодолевая ограничение, заключающееся в том, что AJAX можно использовать только с одним и тем же источником.

По сути, все современные браузеры реализуют стандарт CORS.На самом деле, почти все браузерные ajax-запросы основаны на механизме CORS, но разработчикам внешнего интерфейса это может быть безразлично (поэтому на самом деле текущее решение CORS в основном фон должен быть реализован).

О CORS настоятельно рекомендуется прочитать
Подробное объяснение CORS для междоменного совместного использования ресурсов (Ифэн Жуань)

Кроме того, вот схема реализации (упрощенный вариант):

Как определить, простая ли это просьба?

Браузеры делят запросы CORS на две категории: простые запросы и не очень простые запросы. Пока следующие два условия выполняются одновременно, это простой запрос.

  • Метод запроса — один из следующих трех методов: HEAD, GET, POST.
  • Информация заголовка HTTP не превышает следующих полей:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type (ограничено тремя значениями application/x-www-form-urlencoded, multipart/form-data, text/plain)

Если два вышеуказанных условия не выполняются одновременно, это непростая заявка.

Междоменная производительность Ajax

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

В то время как запрос ajax, если существует явление междоменного и не разрешается, будет иметь следующую производительность :( обратите внимание, что запрос ajax, пожалуйста, не говорите, почему запрос http может, а ajax нет, потому что ajax сопровождается междоменный, поэтому только HTTP-запрос в порядке, этого недостаточно)

Примечание. Конкретную междоменную конфигурацию серверной части см. в заголовке.

Первое явление:No 'Access-Control-Allow-Origin' header is present on the requested resource,а такжеThe response had HTTP status code 404

Причины этого следующие:

  • Этот запрос ajax является «непростым запросом», поэтому предварительный запрос (OPTIONS) будет отправлен перед запросом.
  • Фоновый интерфейс на стороне сервера не разрешает запросы OPTIONS, что приводит к невозможности найти соответствующий адрес интерфейса.

Решение: серверная часть позволяет запрашивать параметры

Второе явление:No 'Access-Control-Allow-Origin' header is present on the requested resource,а такжеThe response had HTTP status code 405

Это явление отличается от первого тем, что в этом случае фоновый метод разрешает запросы OPTIONS, но некоторые конфигурационные файлы (такие как安全配置), блокируя запрос OPTIONS, что вызовет это явление

Решение: серверная часть закрывает соответствующую конфигурацию безопасности.

Третье явление:No 'Access-Control-Allow-Origin' header is present on the requested resource,а такжеstatus 200

Это явление отличается от первого и второго тем, что в этом случае фон на стороне сервера разрешает запросы OPTIONS, а интерфейс также разрешает запросы OPTIONS, но при совпадении заголовка возникает несоответствие.

Например, проверка заголовка источника не соответствует, например, отсутствие поддержки некоторых заголовков (например, общий заголовок X-Requested-With), тогда сервер вернет ответ интерфейсу, и интерфейс сработает. XHR.onerror при обнаружении этого приводит к тому, что интерфейсная консоль сообщает об ошибке.

Решение: добавьте соответствующую поддержку заголовков в серверную часть.

Четвертое явление:heade contains multiple values '*,*'

Явление производительности заключается в том, что в фоновом ответе есть два заголовка HTTP.Access-Control-Allow-Origin:*

Честно говоря, основная причина этой проблемы в том, что человек, который выполняет междоменную настройку, не понимает принципа, что приводит к повторной настройке, такой как:

  • Распространено в фоне .net (обычно ориджин настраивается в web.config, а потом ориджин вручную добавляется в код (например, код вручную ставится на возврат *))
  • Распространено в бэкенде .net (установите Origin: * как в IIS, так и в веб-конфигурации проекта)

Решения (индивидуальная переписка):

  • Рекомендуется удалить *, добавленный вручную в код, и использовать только тот, который указан в конфигурации проекта.
  • Рекомендуется удалить конфигурацию* в IIS и использовать только ту, что находится в конфигурации проекта.

Как решить междоменный ajax

Как правило, междоменное решение ajax решается через JSONP или CORS следующим образом: (обратите внимание, что JSONP сейчас почти не используется, поэтому просто разбирайтесь в JSONP)

JSONP способ решения междоменных проблем

jsonp — это старое решение для решения междоменных проблем (на практике не рекомендуется), вот краткое введение (если JSONP будет использоваться в реальном проекте, библиотека классов, которая инкапсулирует JSONP, такая как JQ, обычно используется для создания ajax Запросы)

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

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

Процесс реализации

Шаги реализации JSONP примерно следующие (см. статью в источнике)

  • Клиентская веб-страница запрашивает данные JSON с сервера, добавляя элемент

    function addScriptTag(src) {
      var script = document.createElement('script');
      script.setAttribute("type","text/javascript");
      script.src = src;
      document.body.appendChild(script);
    }
    
    window.onload = function () {
      addScriptTag('http://example.com/ip?callback=foo');
    }
    
    function foo(data) {
      console.log('response data: ' + JSON.stringify(data));
    };                      
        

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

  • Интерфейс, соответствующий серверу, добавляет слой оболочки функции за пределы возвращаемого параметра.
foo({
  "test": "testData"
});                     
  • Поскольку скрипт, запрошенный элементом

Обратите внимание, что данные, возвращаемые общим интерфейсом JSONP и обычным интерфейсом, различаются, поэтому, если интерфейс должен быть совместим с JSONO, необходимо определить, существует ли соответствующий параметр ключевого слова обратного вызова.Если да, то это запрос JSONP и возвращает данные JSONP, в противном случае возвращает обычные данные

Будьте осторожны

Основываясь на принципе реализации JSONP, JSONP может быть только запросом «GET» и не может выполнять более сложные запросы POST и другие запросы, поэтому в этом случае вам нужно обратиться к следующему CORS для решения междоменного (так что теперь это в основном используется исключенным)

CORS решает междоменные проблемы

Принцип CORS был представлен выше.Основное введение здесь заключается в том, как следует настроить серверную часть для решения проблемы в реальном проекте (поскольку большое количество проектных практик решается серверной частью).Вот некоторые распространенные серверные части.решение :

Фоновая конфигурация PHP

Конфигурация фона PHP почти самая простая из всех фонов, просто выполните следующие шаги:

  • Шаг 1: Настройте фон Php, чтобы разрешить междоменный доступ
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
//主要为跨域CORS配置的两大基本信息,Origin和headers
  • Шаг 2: Настройте междоменный веб-сервер Apache (в httpd.conf)

исходный код

<Directory />
    AllowOverride none
    Require all denied
</Directory>

Измените на следующий код

<Directory />
    Options FollowSymLinks
    AllowOverride none
    Order deny,allow
    Allow from all
</Directory>

Фоновая конфигурация Node.js (экспресс-фреймворк)

Серверная часть Node.js также относительно проста в настройке. Просто настройте его с помощью экспресса следующим образом:

app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By", ' 3.2.1')
        //这段仅仅为了方便返回json而已
    res.header("Content-Type", "application/json;charset=utf-8");
    if(req.method == 'OPTIONS') {
        //让options请求快速返回
        res.sendStatus(200); 
    } else { 
        next(); 
    }
});

Фоновая конфигурация JAVA

Для фоновой настройки JAVA необходимо выполнить следующие шаги:

  • Шаг 1. Получите пакет jar зависимостей

    скачать cors-filter-1.7.jarjava-property-utils-1.9.jarЭти два библиотечных файла находятся в каталоге lib. (Поместите его в раздел webcontent/WEB-INF/lib/ соответствующего проекта)

  • Шаг 2: Если проект создан с помощью Maven, добавьте следующие зависимости в pom.xml: (не-maven игнорируйте)
<dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>cors-filter</artifactId>
    <version>[ version ]</version>
</dependency>

где версия должна быть последней стабильной версией, фильтр CORS

  • Шаг 3. Добавьте конфигурацию CORS в файл Web.xml проекта (App/WEB-INF/web.xml).
<!-- 跨域配置-->    
<filter>
        <!-- The CORS filter with parameters -->
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        
        <!-- Note: All parameters are options, if omitted the CORS 
             Filter will fall back to the respective default values.
          -->
        <init-param>
            <param-name>cors.allowGenericHttpRequests</param-name>
            <param-value>true</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.allowOrigin</param-name>
            <param-value>*</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.allowSubdomains</param-name>
            <param-value>false</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, HEAD, POST, OPTIONS</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.exposedHeaders</param-name>
            <!--这里可以添加一些自己的暴露Headers   -->
            <param-value>X-Test-1, X-Test-2</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.supportsCredentials</param-name>
            <param-value>true</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.maxAge</param-name>
            <param-value>3600</param-value>
        </init-param>

    </filter>

    <filter-mapping>
        <!-- CORS Filter mapping -->
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Обратите внимание, что вышеуказанный файл конфигурации должен быть размещен перед web.xml в качестве первого фильтра (фильтров может быть несколько).

  • Шаг 4. Возможная неправильная конфигурация модуля безопасности

NET фоновая конфигурация

Фоновая конфигурация .NET может относиться к следующим шагам:

  • Шаг 1: Конфигурация веб-сайта

Откройте панель управления, выберите «Администрирование», выберите «iis», щелкните правой кнопкой мыши свой веб-сайт, выберите «Обзор», откройте каталог, в котором находится веб-сайт, откройте файл web.config с помощью Блокнота, добавьте следующую информацию о конфигурации и перезапустите веб-сайт.

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

"Access-Control-Allow-Headers":"X-Requested-With,Content-Type,Accept,Origin"            
  • Шаг 2: Другие дополнительные конфигурации, если после первого шага все еще есть междоменные проблемы, это может быть:

    • Существуют ограничения на некоторые типы запросов в интерфейсе (например, POST и т. д.), пожалуйста, снимите ограничения на данный момент.
    • В интерфейсе конфигурация повторяетсяOrigin:*, пожалуйста, удалите
    • На сервере IIS конфигурация повторяетсяOrigin:*, пожалуйста, удалите

Метод прокси-запроса решает междоменную проблему интерфейса

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

В отличие от предыдущего метода, передний CORS является внутренним решением, и это в основном внешний интерфейс, проксирующий интерфейс, то есть:

  • Внешний ajax-запрос — это локальный интерфейс.
  • После получения запроса локальный интерфейс запрашивает данные у фактического интерфейса, а затем возвращает информацию во внешний интерфейс.
  • Как правило, node.js можно использовать в качестве прокси.

По поводу того, как реализовать прокси, я не буду здесь зацикливаться на описании, способов много и это не сложно, в основном они основаны на node.js.

поиск по ключевому словуnode.js,代理请求Вы можете найти множество вариантов.

Как анализировать кросс-домены ajax

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

Захват данных запроса пакета

Первый шаг, конечно, узнать, какие данные отправил и получил наш запрос ajax.Это не сложно сделать, и нет необходимостиfiddlerи другие инструменты, основанные только наChromeТолько что

  • ChromeБраузер открывает страницу, соответствующую вхождению ajax,F12ОткрытьDev Tools
  • отправить ajax-запрос
  • правая панель ->NetWork->XHR, затем найдите запрос ajax прямо сейчас, нажмите

Пример 1 (обычный ajax-запрос)

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

Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept
Access-Control-Allow-Methods: Get,Post,Put,OPTIONS
Access-Control-Allow-Origin: *

Поэтому, когда браузер получает ответ, он судит о правильности запроса, естественно не сообщит об ошибке, и данные ответа успешно получены.

Пример 2 (Ajax-запрос с междоменной ошибкой)

Для удобства мы все же возьмем пример неправильного исполнения выше в качестве примера.

В этом запросе интерфейс Allow не включаетOPTIONS, поэтому запрос выглядит междоменным,


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

Еще междоменные ошибки в принципе аналогичны, то есть не выполняются три вышеперечисленных (Headers, Allow, Origin), поэтому здесь я их повторять не буду.

Пример 3 (Ajax-запрос, не связанный с междоменным)

Конечно, не все ошибки ajax-запросов связаны с междоменностью, поэтому, пожалуйста, не путайте, например:

Например, в этом запросе нет проблем с его междоменной конфигурацией, это только из-за запросаAcceptи ответContent-TypeПросто не совпадает.

Более

В основном это то, как анализировать запрос ajax черезChromeВы можете узнать, какие данные отправлены, какие получены, а затем сравнить их один за другим, чтобы узнать, в чем проблема.

последние слова

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

Впереди долгий путь, и я надеюсь разделить его с вами!

приложение

использованная литература

блог

Первый выпуск2017.03.22в личном блоге