Solve cross domain -- postMessage

Keywords: Windows JSON html5 Firefox

Principle and implementation of postMessage

In order to solve the problem of cross domain, HTML5 introduces a new API: Cross Document Messaging. This API adds a window.postMessage method to the window object to allow cross window communication, regardless of whether the two windows are homologous or not. postMessage is a new method in h5. postMessage can realize Cross Document Messaging, Internet Explorer 8, Firefox 3, Opera 9, Chrome 3 and Safari 4 support postMessage.
This method can monitor and send cross document message transmission content by binding message event of window.

grammar

otherWindow.postMessage(message, targetOrigin, [transfer]);
  • Other window: a reference to other windows, such as the contentWindow property of iframe, the window object returned by window.open, or the window.frames with a named or numeric index.
  • message the data to be sent to other windows. It will be serialized by the structured clone algorithm. This means that you can safely transfer data objects to the target window without any restrictions.
  • targetOrigin specifies which windows can receive message events through the window's origin property. Its value can be the string "*" (indicating unlimited) or a URI. When sending a message, if any of the protocol, host address or port of the target window does not match the value provided by targetOrigin, the message will not be sent; only if the three match completely, the message will be sent.
  • transfer (optional) is a string of Transferable objects passed at the same time as message. The ownership of these objects will be transferred to the receiver of the message, while the sender does not retain the ownership.

postMessage function

  • Delivering messages across sources
  • Through window.postMessage, it is possible to read and write LocalStorage of other windows.

Delivering messages across sources

An example: the parent window http://aaa.com sends a message to the child window http://bbb.com and calls the postMessage method.

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');

Sending messages from child windows to parent windows is similar.

window.opener.postMessage('Nice to see you', 'http://aaa.com');

Both the parent and child windows can listen to each other's messages through the message event.

window.addEventListener('message', function(e) {
  console.log(e.data);
},false);

The event object event of the message event, which provides the following three properties.

  • event.source: window for sending messages
  • event.origin: the website to which the message is sent
  • event.data: message content

The child window references the parent window through the event.source property and sends the message. Examples are as follows

window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
  event.source.postMessage('Nice to see you!', '*');
}

The event.origin property can filter messages not sent to this window.

window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
  if (event.origin !== 'http://aaa.com') return;
  if (event.data === 'Hello World') {
      event.source.postMessage('Hello', event.origin);
  } else {
    console.log(event.data);
  }
}

Read and write LocalStorage of other windows

The following is an example, the main window writes the localStorage of the iframe child window.

window.onmessage = function(e) {
  if (e.origin !== 'http://bbb.com') {
    return;
  }
  var payload = JSON.parse(e.data);
  localStorage.setItem(payload.key, JSON.stringify(payload.data));
};
The child window writes messages from the parent window to its own LocalStorage.
The code for the parent window to send the message is as follows.
var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
win.postMessage(JSON.stringify({key: 'storage', data: obj}), 'http://bbb.com');
The code to receive messages from the enhanced child window is as follows.
window.onmessage = function(e) {
  if (e.origin !== 'http://bbb.com') return;
  var payload = JSON.parse(e.data);
  switch (payload.method) {
    case 'set':
      localStorage.setItem(payload.key, JSON.stringify(payload.data));
      break;
    case 'get':
      var parent = window.parent;
      var data = localStorage.getItem(payload.key);
      parent.postMessage(data, 'http://aaa.com');
      break;
    case 'remove':
      localStorage.removeItem(payload.key);
      break;
  }
};
The message code of the enhanced parent window is as follows.
var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
// Deposit object
win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://bbb.com');
// read object
win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
window.onmessage = function(e) {
  if (e.origin != 'http://aaa.com') return;
  // "Jack"
  console.log(JSON.parse(e.data).name);
};
Published 4 original articles, won praise 0, visited 77
Private letter follow

Posted by l053r on Wed, 15 Jan 2020 03:27:45 -0800