Правильно сталкивайтесь с междоменными, не паникуйте

JavaScript
Правильно сталкивайтесь с междоменными, не паникуйте

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

Оригинальный адрес:YOU-SHOULD-KNOW-JS

что такое кросс домен

Междоменный означает, что браузер не может выполнять скрипты с других сайтов. Это вызвано политикой одинакового происхождения браузера, ограничение безопасности, которые браузеры налагают на JavaScript.

Политика того же происхождения ограничивает следующее поведение:

  • Файлы cookie, LocalStorage и IndexDB не могут быть прочитаны
  • Объекты DOM и JS не могут быть получены
  • Ajax-запрос не может быть отправлен

Распространенные междоменные сценарии

Так называемая гомология означает, что имя домена, протокол и порт совпадают.

http://www.nealyang.cn/index.html 调用   http://www.nealyang.cn/server.php  非跨域

http://www.nealyang.cn/index.html 调用   http://www.neal.cn/server.php  跨域,主域不同

http://abc.nealyang.cn/index.html 调用   http://def.neal.cn/server.php  跨域,子域名不同

http://www.nealyang.cn:8080/index.html 调用   http://www.nealyang.cn/server.php  跨域,端口不同

https://www.nealyang.cn/index.html 调用   http://www.nealyang.cn/server.php  跨域,协议不同

localhost   调用 127.0.0.1 跨域

междоменное решение

JSONP Cross Domain.

jsonp cross-domain на самом деле является шаблоном прокси в шаблоне проектирования JavaScript. Загрузка файлов статических ресурсов с разных доменных имен через соответствующие теги на html-страницах разрешена браузерами, поэтому мы можем использовать эту «преступную лазейку» для выполнения междоменного выполнения. Как правило, мы можем динамически создавать теги сценария, а затем запрашивать URL-адрес с параметрами для обеспечения междоменной связи.

//原生的实现方式
let script = document.createElement('script');

script.src = 'http://www.nealyang.cn/login?username=Nealyang&callback=callback';

document.body.appendChild(script);

function callback(res) {
  console.log(res);
}

Конечно, jquery также поддерживает реализацию jsonp.

$.ajax({
    url:'http://www.nealyang.cn/login',
    type:'GET',
    dataType:'jsonp',//请求方式为jsonp
    jsonpCallback:'callback',
    data:{
        "username":"Nealyang"
    }
})

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

document.domain + перекрестный домен iframe

Главное в этом междоменном методе — требуется одно и то же основное доменное имя. Что совпадает с основным доменным именем? www.nealyang.cn aaa.nealyang.cn ba.ad.nealyang.cn Все эти три основных доменных имени являются nealyang.cn, и этот метод нельзя использовать, если основные доменные имена отличаются.

Предположим, что в настоящее время a.nealyang.cn и b.nealyang.cn соответствуют серверам, указывающим на разные IP-адреса.

Есть test.html file a.neylang.cn

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>html</title>
    <script type="text/javascript" src = "jquery-1.12.1.js"></script>
</head>
<body>
    <div>A页面</div>
    <iframe 
    style = "display : none" 
    name = "iframe1" 
    id = "iframe" 
    src="http://b.nealyang.cn/1.html" frameborder="0"></iframe>
    <script type="text/javascript">
        $(function(){
            try{
                document.domain = "nealyang.cn"
            }catch(e){}
            $("#iframe").load(function(){
                var jq = document.getElementById('iframe').contentWindow.$
                jq.get("http://nealyang.cn/test.json",function(data){
                    console.log(data);
                });
            })
        })
    </script>
</body>
</html>

Используйте iframe для загрузки файлов в других доменах (nealyang.cn/1.html) и установите для document.domain значение nealyang.cn. После загрузки iframe вы можете получить глобальные объекты в домене nealyang.cn. В это время попробуйте запросить test.json под доменным именем nealyang.cn (в это время вы можете запросить интерфейс), и вы обнаружите, что запрос данных завершается ошибкой~~ Неудивительно, не удивительно! ! ! ! ! ! !

Запрос данных не удался, цель не достигнута, естественно на один шаг меньше:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>html</title>
    <script type="text/javascript" src = "jquery-1.12.1.js"></script>
    <script type="text/javascript">
        $(function(){
            try{
                document.domain = "nealyang.com"
            }catch(e){}
        })
    </script>
</head>
<body>
    <div id = "div1">B页面</div>
</body>
</html>

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

междоменное окно.имя + iframe

Свойство window.name устанавливает или возвращает строку, содержащую имя окна. Его артефакт заключается в том, что значение имени все еще существует после загрузки на разных страницах или в разных доменах, оно не изменится без модификации и может хранить очень длинные имена (2 МБ).

Предполагая, что индексная страница запрашивает данные на удаленном сервере, мы создаем тег iframe под страницей, src iframe указывает на адрес файла сервера (src тега iframe может быть междоменным), устанавливаем значение window.name в файле сервера, а затем затем прочитайте значение window.name в iframe в index.html. идеально~

<body>
  <script type="text/javascript"> 
    iframe = document.createElement('iframe'),
    iframe.src = 'http://localhost:8080/data.php';
    document.body.appendChild(iframe);
    iframe.onload = function() {
      console.log(iframe.contentWindow.name)
    };
  </script>
</body>

Конечно, этого недостаточно.

Поскольку оговорено, что если src страницы index.html и фрейм iframe на странице имеют разное происхождение, то ничем во фрейме нельзя манипулировать, поэтому нельзя получить значение имени фрейма iframe, сообщая вам, что мы не из одной семьи Вы даже не можете получить мои данные здесь. Поскольку мы хотим иметь то же происхождение, то измените src для ссылки.Как упоминалось ранее, значение window.name не изменится независимо от того, как мы его загружаем, поэтому мы создали новую пустую страницу proxy.html в тот же каталог, что и index.html, и измененный код выглядит следующим образом:

<body>
  <script type="text/javascript"> 
    iframe = document.createElement('iframe'),
    iframe.src = 'http://localhost:8080/data.php';
    document.body.appendChild(iframe);
    iframe.onload = function() {
      iframe.src = 'http://localhost:81/cross-domain/proxy.html';
      console.log(iframe.contentWindow.name)
    };
  </script>
</body>

Идеал кажется очень хорошим Во время процесса загрузки iframe быстро сбросьте точку iframe.src, чтобы сделать его тем же источником, что и index.html, тогда индексная страница сможет получить свое значение имени! Но реальность жестока, производительность iframe в реальности постоянно обновляется, Также хорошо понятно, что после каждого срабатывания времени onload сброс src эквивалентен перезагрузке страницы и срабатыванию события onload, поэтому он постоянно обновляется (но нужные данные все равно могут быть выведены). Модифицированный код выглядит следующим образом:

<body>
  <script type="text/javascript"> 
    iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    var state = 0;
    
    iframe.onload = function() {
      if(state === 1) {
          var data = JSON.parse(iframe.contentWindow.name);
          console.log(data);
          iframe.contentWindow.document.write('');
          iframe.contentWindow.close();
        document.body.removeChild(iframe);
      } else if(state === 0) {
          state = 1;
          iframe.contentWindow.location = 'http://localhost:81/cross-domain/proxy.html';
      }
    };

    iframe.src = 'http://localhost:8080/data.php';
    document.body.appendChild(iframe);
  </script>
</body>

Итак, как и выше, мы получаем данные, возвращаемые сервером, но есть несколько обязательных условий:

  • Междоменные возможности тегов iframe
  • Возможность сохранения значения свойства window.names при обновлении документа.

location.hash + междоменный iframe

Этот междоменный метод аналогичен описанному выше, он также динамически вставляет iframe и устанавливает его src в качестве адреса сервера, сервер также выводит один конец кода js, а также завершает передачу данных через общение с дочерними окнами.

Я думаю, что все уже знают о точке привязки, на самом деле это установка точки привязки и предоставление документу указания соответствующей позиции. Точка привязки устанавливается с помощью тега, а затем href указывает на идентификатор для перехода.Конечно, предполагается, что у вас должна быть полоса прокрутки, иначе ее будет нелегко прокручивать, верно?

И location.hash на самом деле является якорем URL-адреса. Например, после открытия URL-адреса http://www.nealyang.cn#Nealyang ввод location.hash в консоли вернет поле #Nealyang.

Базовые знания завершены, поговорим о том, как добиться кроссдоменности

Если страница индекса хочет получить данные удаленного сервера, динамически вставьте iframe и выполните src iframe по адресу сервера.В это время верхнее окно и дочернее окно, которое обертывает iframe, не могут взаимодействовать , Из-за политики того же происхождения достаточно изменить путь дочернего окна, загрузить данные по пути как хэш-значение измененного пути, а затем вы можете общаться. Добавьте данные в хэш адреса индексной страницы, Индексная страница прослушивает изменения хэша, метод hashchange h5

<body>
  <script type="text/javascript">
    function getData(url, fn) {
      var iframe = document.createElement('iframe');
      iframe.style.display = 'none';
      iframe.src = url;

      iframe.onload = function() {
        fn(iframe.contentWindow.location.hash.substring(1));
        window.location.hash = '';
        document.body.removeChild(iframe);
      };

      document.body.appendChild(iframe);
    }

    // get data from server
    var url = 'http://localhost:8080/data.php';
    getData(url, function(data) {
      var jsondata = JSON.parse(data);
      console.log(jsondata.name + ' ' + jsondata.age);
    });
  </script>
</body>

Дополнительное примечание: Фактически, location.hash и window.name похожи, оба являются методами использования глобальных свойств объекта, а затем эти два метода совпадают с jsonp, то есть могут быть реализованы только запросы на получение

postMessage кросс-доменный

Это прохладный API, предложенный H5, IE8 +, Chrome, FF все поддерживает и реализовал эту функцию. Эта функция также очень проста, включая время сообщения для получения информации и метода PostMessage для отправки информации.

Метод postMessage для отправки информации заключается в отправке информации во внешнее окно.

otherWindow.postMessage(message,targetOrigin);

otherWindow относится к целевому окну, то есть к окну, которому должно быть отправлено сообщение, является членом свойства window.frames или окном, созданным методом window.open. Message — сообщение для отправки, тип — String, Object (IE8, 9 не поддерживают Obj), targetOrigin — ограниченный диапазон приема сообщений, используйте звездочку *, если ограничений нет

событие сообщения, которое принимает информацию

var onmessage = function(event) {
  var data = event.data;
  var origin = event.origin;
}

if(typeof window.addEventListener != 'undefined'){
    window.addEventListener('message',onmessage,false);
}else if(typeof window.attachEvent != 'undefined'){
    window.attachEvent('onmessage', onmessage);
}

взять каштан

a.html(www.nealyang.cn/a.html)

<iframe id="iframe" src="http://www.neal.cn/b.html" style="display:none;"></iframe>
<script>       
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = {
            name: 'aym'
        };
        // 向neal传送跨域数据
        iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.neal.cn');
    };

    // 接受domain2返回数据
    window.addEventListener('message', function(e) {
        alert('data from neal ---> ' + e.data);
    }, false);
</script>

b.html(www.neal.cn/b.html)

<script>
    // 接收domain1的数据
    window.addEventListener('message', function(e) {
        alert('data from nealyang ---> ' + e.data);

        var data = JSON.parse(e.data);
        if (data) {
            data.number = 16;

            // 处理后再发回nealyang
            window.parent.postMessage(JSON.stringify(data), 'http://www.nealyang.cn');
        }
    }, false);
</script>

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

Потому что в настоящее время это основное междоменное решение. Вот еще немного.

Введение

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

CORS требует поддержки как браузера, так и сервера. В настоящее время все браузеры поддерживают эту функцию, и браузер IE не может быть ниже IE10. IE8+: IE8/9 требует, чтобы объект XDomainRequest поддерживал CORS.

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

две просьбы

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

  • Метод запроса: HEAD, POST или GET.
  • Информация заголовка http не выходит за пределы следующих полей: Accept, Accept-Language, Content-Language, Last-Event-ID, Content-Type (ограничено тремя значениями: application/x-www-form-urlencoded, multipart/form- данные, текст / обычный)

Почему он разделен на простые запросы и непростые запросы, ведь браузеры по-разному обрабатывают эти два метода запроса.

простой запрос

Основной процесс

Для простых запросов браузер делает запросы CORS напрямую. В частности, к информации заголовка добавляется поле Origin. Ниже приведен пример: Браузер определяет, что этот AJAX-запрос из разных источников является простым запросом, и автоматически добавляет поле Origin к информации заголовка.

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0
...

Поле Origin используется для указания источника (протокол + доменное имя + порт), из которого исходит этот запрос. На основе этого значения сервер решает, соглашаться ли на запрос.

Если источник, указанный Origin, не входит в разрешенную область, сервер вернет обычный HTTP-ответ. Браузер обнаруживает, что информация заголовка этого ответа не содержит поля Access-Control-Allow-Origin (подробности см. ниже), и знает, что произошла ошибка, поэтому выдает ошибку, которая перехватывается функцией обратного вызова onerror. XMLHttpRequest.

Обратите внимание, что этот тип ошибки не может быть идентифицирован по коду состояния, потому что код состояния ответа HTTP может быть 200.

Если доменное имя, указанное Origin, находится в допустимом диапазоне, ответ, возвращаемый сервером, будет содержать несколько дополнительных полей заголовка.

   Access-Control-Allow-Origin: http://api.bob.com
   Access-Control-Allow-Credentials: true
   Access-Control-Expose-Headers: FooBar
   Content-Type: text/html; charset=utf-8

В приведенной выше информации заголовка есть три поля, относящиеся к запросам CORS, все они начинаются с Access-Control-

  • Access-Control-Allow-Origin: это поле обязательно для заполнения. Его значением является либо значение поля Origin на момент запроса, либо символ *, указывающий, что принимаются запросы для любого доменного имени.
  • Access-Control-Allow-Credentials: Это поле является необязательным. Его значение является логическим значением, указывающим, разрешать ли отправку файлов cookie. По умолчанию файлы cookie не включаются в запросы CORS. Если установлено значение true, это означает, что сервер явно разрешает включить файл cookie в запрос и отправить его на сервер вместе. Это значение может быть установлено только в true.Если сервер не хочет, чтобы браузер отправлял файлы cookie, просто удалите это поле.
  • Access-Control-Expose-Headers: Это поле является необязательным. При выполнении запроса CORS метод getResponseHeader() объекта XMLHttpRequest может получить только 6 основных полей: Cache-Control, Content-Language, Content-Type, Expires, Last-Modified и Pragma. Если вы хотите получить другие поля, вы должны указать их в Access-Control-Expose-Headers.
свойство withCredentials

Как упоминалось выше, запросы CORS по умолчанию не отправляют файлы cookie и данные аутентификации HTTP. Если вы хотите отправить cookie на сервер, с одной стороны, вам нужно согласие сервера, и укажите поле Access-Control-Allow-Credentials.

С другой стороны, разработчик должен включить атрибут withCredentials в запросе AJAX.

var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容

// 前端设置是否带cookie
xhr.withCredentials = true;

xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');

xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText);
    }
};

// jquery
$.ajax({
    ...
   xhrFields: {
       withCredentials: true    // 前端设置是否带cookie
   },
   crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
    ...
});

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

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

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

Непростой запрос — это запрос, который имеет особые требования к серверу, такие как метод запроса PUT или DELETE, или тип поля Content-Type — application/json.

Для запросов CORS, которые не являются простыми запросами, перед формальным общением будет добавлен запрос HTTP-запроса, который называется предварительным запросом.

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

var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();

Браузер обнаруживает, что это непростой запрос, и автоматически выдает «предварительный» запрос, запрашивая у сервера подтверждение того, что его можно запросить. Ниже приведена информация заголовка HTTP для этого «предварительного» запроса.

    OPTIONS /cors HTTP/1.1
   Origin: http://api.bob.com
   Access-Control-Request-Method: PUT
   Access-Control-Request-Headers: X-Custom-Header
   Host: api.alice.com
   Accept-Language: en-US
   Connection: keep-alive
   User-Agent: Mozilla/5.0...

Метод запроса, используемый для «предварительного» запроса, — OPTIONS, что означает, что этот запрос используется для запроса. В информации заголовка ключевым полем является Origin, которое указывает, из какого источника пришел запрос.

В дополнение к полю Origin заголовок запроса «preflight» включает два специальных поля.

  • Access-Control-Request-Method: это поле необходимо для перечисления методов HTTP, которые будут использоваться в CORS-запросе браузера.В приведенном выше примере используется PUT.
  • Access-Control-Request-Headers: это поле представляет собой строку с разделителями-запятыми, которая указывает дополнительные информационные поля заголовка, которые будут отправлять запросы CORS браузера.Приведенный выше пример — X-Custom-Header.
Ответ на предварительный запрос

После того, как сервер получит «предварительный» запрос, проверив поля Origin, Access-Control-Request-Method и Access-Control-Request-Headers и подтвердив, что запросы между источниками разрешены, он может ответить

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

В приведенном выше ответе HTTP ключом является поле Access-Control-Allow-Origin, указывающее, что http://api.bob.com может запрашивать данные. В этом поле также можно установить звездочку, чтобы указать согласие на любой запрос из другого источника.

Если браузер отклоняет запрос «предварительной проверки», он вернет обычный HTTP-ответ, но без каких-либо полей заголовка, связанных с CORS. В это время браузер решит, что сервер не согласен с предварительным запросом, и, таким образом, вызовет ошибку, которая перехватывается функцией обратного вызова onerror объекта XMLHttpRequest. Консоль выведет следующее сообщение об ошибке.

Другие поля, связанные с CORS, на которые отвечает сервер, следующие:

Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
  • Access-Control-Allow-Methods: это поле является обязательным, и его значение представляет собой строку с разделителями-запятыми, указывающую все методы, поддерживаемые сервером для междоменных запросов. Обратите внимание, что возвращаются все поддерживаемые методы, а не только запрошенный браузером. Это сделано для того, чтобы избежать множественных "предполетных" запросов.
  • Access-Control-Allow-Headers: поле Access-Control-Allow-Headers является обязательным, если запрос браузера включает поле Access-Control-Request-Headers. Это также строка с разделителями-запятыми, указывающая все поля заголовка, поддерживаемые сервером, не ограничиваясь теми, которые запрошены браузером в «предпечатной проверке».
  • Access-Control-Allow-Credentials: это поле имеет то же значение, что и для простого запроса.
  • Access-Control-Max-Age: это поле является необязательным и используется для указания периода действия этого запроса предварительной проверки в секундах. В приведенном выше результате период действия составляет 20 дней (1 728 000 секунд), что означает, что ответ разрешено кэшировать в течение 1 728 000 секунд (то есть 20 дней). В течение этого периода нет необходимости выдавать еще один предварительный запрос. .
Браузер нормально отвечает

После того как сервер передаст «предпечатный» запрос, каждый последующий обычный CORS-запрос браузера будет таким же, как и простой запрос, и появится поле заголовка Origin. Ответ сервера также будет иметь поле заголовка Access-Control-Allow-Origin.

PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

Обычный запрос CORS из браузера. Поле происхождения вышеуказанной информации заголовка автоматически добавляется браузером. Ниже приведен нормальный ответ сервера.

Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf-8

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

заключительные замечания

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

Междоменный протокол WebSocket

Протокол WebSocket — это новый протокол в HTML5. Он реализует полнодуплексную связь между браузером и сервером и позволяет осуществлять междоменную связь, что является хорошей реализацией технологии push-уведомлений сервера.

Нативный WebSocket API неудобен в использовании, мы используем Socket.io, который хорошо инкапсулирует интерфейс webSocket, предоставляет более простой и гибкий интерфейс и обеспечивает обратную совместимость для браузеров, не поддерживающих webSocket.

Интерфейсный код:

<div>user input:<input type="text"></div>
<script src="./socket.io.js"></script>
<script>
var socket = io('http://www.domain2.com:8080');

// 连接成功处理
socket.on('connect', function() {
    // 监听服务端消息
    socket.on('message', function(msg) {
        console.log('data from server: ---> ' + msg); 
    });

    // 监听服务端关闭
    socket.on('disconnect', function() { 
        console.log('Server socket has closed.'); 
    });
});

document.getElementsByTagName('input')[0].onblur = function() {
    socket.send(this.value);
};
</script>

node Server

var http = require('http');
var socket = require('socket.io');

// 启http服务
var server = http.createServer(function(req, res) {
    res.writeHead(200, {
        'Content-type': 'text/html'
    });
    res.end();
});

server.listen('8080');
console.log('Server is running at port 8080...');

// 监听socket连接
socket.listen(server).on('connection', function(client) {
    // 接收信息
    client.on('message', function(msg) {
        client.send('hello:' + msg);
        console.log('data from client: ---> ' + msg);
    });

    // 断开处理
    client.on('disconnect', function() {
        console.log('Client socket has closed.'); 
    });
});

перекрестный домен прокси узла

Промежуточное программное обеспечение узла реализует междоменный прокси, запуская прокси-сервер для реализации пересылки данных.Вы также можете изменить имя домена в файле cookie в заголовке ответа, установив параметр cookieDomainRewrite для реализации записи файла cookie текущего домена, что удобно для аутентификации входа в интерфейс.

Создайте прокси-сервер с node + express + http-proxy-middleware

интерфейсный код

var xhr = new XMLHttpRequest();

// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;

// 访问http-proxy-middleware代理服务器
xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true);
xhr.send();

внутренний код

var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();

app.use('/', proxy({
    // 代理跨域目标接口
    target: 'http://www.domain2.com:8080',
    changeOrigin: true,

    // 修改响应头信息,实现跨域并允许带cookie
    onProxyRes: function(proxyRes, req, res) {
        res.header('Access-Control-Allow-Origin', 'http://www.domain1.com');
        res.header('Access-Control-Allow-Credentials', 'true');
    },

    // 修改响应信息中的cookie域名
    cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
}));

app.listen(3000);
console.log('Proxy server is listen at port 3000...');

междоменный прокси nginx

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

общаться с

Приглашаем присоединиться к стеку технологий реагирования, группе QQ для чата передовых технологий.

Обсуждение передовых технологий: 604953717
Стек технологий React: 398240621

Обратите внимание на официальный аккаунт: [Full-stack front-end selection] Получайте хорошие рекомендации статей каждый день. Вы также можете присоединиться к группе и учиться и общаться вместе~~

Справочная документация

Вууху. Руан Ифэн.com/blog/2016/0… сегмент fault.com/ah/119000001…