How do I postMessage to a sibling iFrame

2020-02-13 01:55发布

问题:

I'm looking for a way to postMessage to a sibling iFrame without any javascript in the parent page. The difficulty I'm having is trying to get the window object for the other iFrame from the first iFrame

The page would be laid out something like this:

html body (http://host.com/)
  iFrame#a (http://me.com/a)
  iFrame#b (http://me.com/b)

From iFrame#a I'm trying to do:

(iFrame#b window).postMessage(...)

The problem is I don't know how to get the window object for iFrame#b from within iFrame#a. parent.getElementById() and other functions are subject to XSS restrictions. I just want to emit a postMessage to all other iFrames on the parent page that are from my domain http://me.com/ in the example above.

回答1:

While it is true that it is not possible to interact with another window/iframe that is on another domain, it is possible to get references to such a window/iframe and all the child iframes embedded into that window/iframe. The way to do it is to use window.top.frames (to access the top window object) or window.parent.frames (to access the direct parent window object, while there may be other higher-level ancestors). No need to use getElementById or other DOM-related function. See this for more info: https://developer.mozilla.org/en-US/docs/DOM/window.frames

The window.frames property returns an array-like object which you can then iterate over and do a postMessage on each iframe. This will not trigger the same-origin restrictions since you are not interacting with any window in any way except than using postMessage on them. Since you want to do a postMessage on every iframe from a specific domain, you can just do:

var frames = window.parent.frames;
for (var i = 0; i < frames.length; i++) { 
  frames[i].postMessage("hello", targetDomain);
}


回答2:

You will not be able to do this as an iframe cannot interact with the page it's emedded within (nor anything within that page), unless the parent is under the same domain (which, in your example, it is not). If it could, it would pose XSS security issues as you indicated that you're aware of.

Instead, you could:

  • Set a cookie in /a/ and poll for it in /b/ (this is going to be expensive though as /b/ would have to somehow keep making calls to the server)
  • Use a 'HTML5' persistent data storage mechanism, storing the data from /a/ and poll for it in /b/ (perhaps localStorage could be used)
  • Use a websocket to link all of your siblings via the server
  • Reconsider what you're trying to do: it sounds very odd what you're trying to achieve - are you sure there isn't a better way of doing things than using iframes like this?