Iframes and the postMessage Method
JavaScript can be used to communicate between documents when using iframes, as discussed at Iframes and Cross-Document Communication. However, if the documents are not on the same domain, the same-origin policy prevents access to most objects and properties and will trigger access denied errors when JavaScript attempts communication.
Cross-Document Messaging with postMessage
is designed to provide a safe means of communication between documents on different domains while still offering protection from cross-site scripting attacks. This method can be used with iframes as well as between windows when the window.open
method is used by one to open another.
How to Use postMessage
There are two basic components to cross-document messaging: the postMessage
method invocation, and the onmessage
event handler set up in the receiving document to respond to incoming messages.
To send a message from one document to another, begin by obtaining a reference to the window you want to send a message to. If sending a message to a document in an iframe, first get a reference to the iframe and then its contentWindow
property as shown below. If sending a message from the iframed document to the containing document, the parent
keyword provides a reference.
If sending a message to a window opened using the window.open
method, a reference is returned from the method. If sending a message from a window opened using the window.open
method, the opener
property of the window provides that reference.
postMessage Arguments
The postMessage
method takes two arguments: the message to be sent (data), and the domain to which you wish to send it (formally referred to as the target origin):
// get reference to window inside the iframe
var wn = document.getElementById('ifrm').contentWindow;
// postMessage arguments: data to send, target origin
wn.postMessage('Hello to iframe from parent!', 'http://www.example.com');
The postMessage
method supports data types including strings, numbers, arrays, and objects. The target origin argument includes the protocol, host, and optionally, the port of the document to receive the message. Target origin can also be specified using an "*"
(any origin) or "/"
(the same origin as the document sending the message). If the origin of the target window doesn't match the specified origin, the message is not sent.
The Message Event
When a message is sent using postMessage, a message
event is fired on the destination window. In order to process the event, you need a message event handler. You can use addEventListener
to assign a handler for the message event, or you can assign a function to the onmessage
property of the window object.
window.addEventListener('message', handleMessage, false);
An event
object is passed to the message event handler. The message event
includes the following properties:
- data
- the message being sent
- origin
- the origin of the document that sent the message (protocol, hostname, and possibly port)
- source
- a reference to the window object from which the message came
The following message event handler function demonstrates how these properties can be used:
// message event handler (e is event object)
function handleMessage(e) {
// Reference to element for data display
var el = document.getElementById('display');
// Check origin
if ( e.origin === 'http://www.example.com' ) {
// Retrieve data sent in postMessage
el.innerHTML = e.data;
// Send reply to source of message
e.source.postMessage('Message received', e.origin);
}
}
Security Considerations
The postMessage specification recommends the following steps to ensure the safety of the process when using cross-document messaging:
- Check the origin attribute to ensure that messages are only accepted from domains that you expect to receive messages from.
- If you don't check the origin attribute and instead accept messages from any origin, keep in mind the potential risk for denial-of-service attacks. Controlling the number of messages accepted per minute could offer protection in this case.
- Check the data received to be sure it is the type of data you are expecting.
- Don't use the wildcard target origin (
"*"
) when sending messages that contain confidential information.