Краткое изложение распространенных методов внешнего междоменного взаимодействия

Безопасность

Добавить Автора
Блог:yeaseonzhang.github.io
Оригинальная ссылка

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

Та же политика происхождения

за чтоперекрестный домен,перекрестный доменотносительно гомологии. Если протокол, доменное имя и порт совпадают, тогомология.
браузер черезТа же политика происхожденияОграничивает взаимодействие документов или сценариев, загруженных из одного источника, с ресурсами из другого источника. Это ключевой механизм безопасности для изоляции потенциально вредоносных файлов, выдержки изMDN.

Общие решения

document.domain

Эта схема в основном используется для междоменных ситуаций, когда основной домен один и тот же, а поддомены разные. Например:https://jdc.jd.com/а такжеhttps://www.jd.com/.

вwww.jd.com/открыть одинjdc.jd.com/, доменное имя JDCjdc.jd.com/, который выполняется через консольdocument.domain = 'jd.com';. Принудительно настроить основной домен для достижения того же источника.

var jdc = window.open('https://jdc.jd.com/');
// JDC 页面加载完成后执行
var divs = jdc.document.getElementsByTagName('div');

$(divs).css('border', '1px solid red');

Обычная практика - пройтиiframe加载一个跨域页面资源。 потому чтоwindow.openДанным методом будет запрещено разговаривать в браузере.

domain.com/index.html

<iframe id="sub" src="http://sub.domain.com/index.html"></iframe>
<script>
  var username = 'yeseonzhang';
</script>

sub.domain.com/index.html

<script>
  document.domain = 'domain.com';
  console.log(window.parent.username);
</script>

location.hash

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

На приведенном выше рисунке показано отношение включения трех страниц, аhashпроцесс передачи.

domain-a.com/a.html

<iframe id="iframe-b" src="http://domain-b.com/b.html"></iframe>
<script>
  var bPage = document.getElementById('iframe-b');

  /* step 1 */
  bPage.src = bPage.src + '#user=yeaseonzhang';

  function cb (res) {
    console.log(res);
  }
</script>

domain-b.com/b.html

<iframe id="iframe-c" src="http://domain-a.com/c.html"></iframe>
<script>
  var cPage = document.getElementById('iframe-c');

  window.onhashchange = function () {
    /* step 2 */
    cPage.src = cPage.src + location.hash;
  }
</script>

domain-a.com/c.html

<script>
  window.onhashchange = function () {
    /* step 3 */
     window.parent.parent.cb('success: ' + location.hash);
  }
</script>

из-застраницаа такжеc страницаэто тот же ресурс домена, поэтомуc страницав состоянии пройтиwindow.parent.parentдоступстраницаресурс.

window.name

Эта схема аналогичнаlocation.hash, которому должна помочь третья страница.
window.nameСвойства используются для получения/установки имени окна. Следует отметить, что текущее окноwindow.nameОн не изменится из-за перезагрузки страницы и переходов, поэтому вы можете использовать эту функцию для конвертации междоменныхwindow.nameЧитать, перенаправляя на ту же страницу домена.

domain-a.com/a.html

<script>
  var iframe = document.createElement('iframe');
  /* step 1 加载跨域页面 */
  iframe.src = 'http://domain-b.com/b.html';
  var domain = 'diff';

  /* 监听iframe加载 */
  iframe.onload = function () {
    if ('diff' == domain) {
      /* step 2 重定向到同域页面 */
      iframe.contentWindow.location = 'http://www.domain-a.com/c.html';
      domain = 'same';
    } else if ('same' == domain) {
      /* 获取同域资源的window.name信息 */
      cb(iframe.contentWindow.name);
      /* 清空数据 */
      iframe.contentWindow.name = '';
    }
  }

  function cb (res) {
    console.log(JSON.parse(res));
  }
</script>

domain-b.com/b.html

<scirpt>
  /* 写入相关数据 */
  var obj = {
    username: 'yeaseonzhang'
  }
  window.name = JSON.stringify(obj);
</script>

domain-a.com/c.html

Тот же доменc страница, может быть пустой страницей, никаких действий не требуется.

JSONP

JSONP(JSON с дополнением) даJSONспособ его использования. Таким образом, пользователь может пройтиcallbackПараметр передается серверу, и когда сервер возвращает данные, параметр обратного вызова будет использоваться в качестве имени функции для переноса данных JSON.

Как мы все знаем, все html-страницы сsrcметка атрибута (<img>,<script>а такжеiframe) имеют междоменные возможности. Поэтому самый простой способ реализовать это — динамически загружать JS.

клиент

function todo(data){
  console.log('The author is: '+ data.name);
}

var script = document.createElement('script');
/* callback参数,用来指定回调函数的名字。 */
script.src = 'http://www.yeaseonzhang.com/author?callback=todo';
document.body.appendChild(script);

Сервер

/* 服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。 */
todo({"name": "yeaseonzhang"});

todo()Функция будет выполняться как глобальная функция, пока она определенаtodo()функция, функция будет вызвана немедленно.

postMessage

window.postMessage— это безопасный API обмена сообщениями на основе событий в HTML5.

otherWindow.postMessage(message, targetOrigin, [transfer]);

postMessage(), метод содержит три параметра:

  • message: содержание сообщения
  • targetOrigin: принять источник окна сообщения, то есть "протокол + имя домена + порт". Также можно установить подстановочные знаки*, отправить на все окна
  • transfer: необязательный параметр (логическое значение), представляющий собой строку, передаваемую одновременно с сообщением.TransferableОбъекты. Право собственности на эти объекты будет передано получателю сообщения, а отправитель больше не сохранит право собственности.

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

  • event.source: ссылка на объект окна, отправивший сообщение, который можно использовать для установления двусторонней связи между двумя окнами.
  • event.origin: URI для отправки сообщения
  • event.data: содержание сообщения

отправитель:domain-a.com/a.html

<script>
  var newWindow = window.open('http://domain-b.com/b.html');
  /* 向b.html发送消息 */
  newWindow.postMessage('Hello', 'http://domain-b.com/b.html');

  /* 双向通信,接收b.html的回复消息 */
  var onmessage = function (event) {
    var data = event.data;
    var origin = event.origin;
    var source = event.source;
    if (origin == 'http://domain-b.com/b.html') {
      console.log(data); //Nice to see you!
    }
  };
  window.addEventListener('message', onmessage, false);
</scirpt>

Получатель:domain-b.com/b.html

<script>
  var onmessage = function (event) {
    var data = event.data;
    var origin = event.origin;
    var source = event.source;
    if (origin == 'http://domain-a.com/a.html') {
      console.log(data); //Hello
      /* 回复a.html的消息 */
      source.postMessage('Nice to see you!', 'http://domain-a.com/a.html');
    }
  };
  window.addEventListener('message', onmessage, false);
</script>

WebSocket

WebSocketЭто новый протокол HTML5, реализующий полнодуплексную связь между браузером и сервером, а также междоменное решение.MDN.

/* websocket协议为ws/wss, 类似http/https的区别 */
wsUrl = 'wss://127.0.0.1:8090/ws/';

/* 发送 */
ws = new WebSocket(wsUrl);

/* 连接成功建立时调用 */
ws.onopen = function (event) {
  console.log("websocket command onopen");
  var msg = {
    username: 'YeaseonZhang'
  }
  /* 通过 send() 方法向服务端发送消息,参数必须为字符串 */
  ws.send(JSON.stringify(msg));
};

/* 服务端向客户端发送消息时调用 */
ws.onmessage = function (event) {
  /* event.data包含了服务端发送过来的消息 */
  console.log("websocket command onmessage: " + event.data);
  if (event.data === 'success') {
    /* 通过 close() 方法断开websocket连接 */
    ws.close();
  }
};

/* 连接被关闭时调用 */
ws.onclose = function (event) {
  console.log("websocket command onclose: " + event.data);
};

/* 出现错误时调用 */
ws.onerror = function (event) {
  console.log("websocket command onerror: " + event.data);
};

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

CORS

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

Только back-end поддерживает одноклассники, а front-end не нужно делать много лишней работы (кроме переноскиcookie).

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

Эпилог

Вышеупомянутое междоменное решение, которое я знаю, надеюсь, поможет вам.