I use postMessage to send events from an iframe to it's parent document. I have control over both sides but the content comes from two different domains.

enter image description here

My simple problem is, that i can not identify the iFrame inside of it's parent callback method. The implementation looks like this:

In the iFrame:

parent.postMessage(JSON.stringify({action: "closeView" }),'*');

In the parent window:

window.addEventListener('message',function(event) {
if(event.origin !== 'https://example.com')
    return;

    // Parse message back to json
    var messageObject = JSON.parse(event.data);
    var source = event.source;
    /* this is returning: Window -URL- */
    console.log( source );
    /* This will throw Permission denied, although this code is inside of "parent" */
    console.log(source.parentNode);
},false);

I want to identify a certain parent element of the iframe, which is (logically) inside of the parent document.

When i try to use event.source.parentNode or some jQuery on said object, Firefox says, i can not do this to prevent XSS, error: Error: Permission denied to access property 'parentNode'

How can i get the parent element of the iFrame, that triggered the postMessage event listener?

有帮助吗?

解决方案

you can use window names for this, as they pass from iframe tag to iframe context.

parent doc:

<iframe name=fr2 src="data:text/html,%3Chtml%3E%0A%20%3Cscript%3E%20parent.postMessage%28%7Bname%3A%20window.name%7D%2C%20%22*%22%29%3B%3C/script%3E%0A%3C/html%3E"></iframe>
<iframe name=fr3 src="data:text/html,%3Chtml%3E%0A%20%3Cscript%3E%20parent.postMessage%28%7Bname%3A%20name%7D%2C%20%22*%22%29%3B%3C/script%3E%0A%3C/html%3E"></iframe>

<script>onmessage = function(e){ // use real event handlers in production
       alert("from frame: " + e.data.name);
 };</script>

iframe doc:

<html>
 <script> parent.postMessage({name: name}, "*");</script>
</html>

which alerts "fr2", then "fr3". you can then easily use the name attrib to find the iframe in the parent DOM using attrib CSS selectors.

illustrative demo of window.name+iframe concept: http://pagedemos.com/namingframes/

this painfully simple approach is also immune to issues arising from same-url iframes.

其他提示

As per my understanding this may be try here suppose your main window's url is www.abc.com\home.php

  <body>
         <iframe src="www.abc.com\getOtherDomainContent.php?otherUrl=www.xyz.com"/>
    </body>

getOtherDomainContent.php in this file need to write ajax call which get cross url content and push that content in current iframe window(getOtherDomainContent.php)'s body part.

getOtherDomainContent.php Code:

    <html>
         <head>
//import jqry lib or other you use.
          <script>
              $(document).ready({
               //getcontent of xyz.com
                var otherUrlContent=getAjaxHtml("www.xyz.com");
                 $("body").html(otherUrlContent);
                  // further  code after content pushed.
                  //you can easily access "parent.document" and else using parent which will give you all thing you want to do with your main window
                });
          </script>
         </head>
    </html>

Like seen in this thread: postMessage Source IFrame it is possible to compare each iframes contentWindow with event.source like this:

/*each(iframe...){ */
frames[i].contentWindow === event.source

But i did not like this too much. My solution for now looks like this:

In the iFrame:

parent.postMessage(JSON.stringify({action: "closeView", viewUrl: document.URL}),'*');

Update: docuent.URL can become a problem, when you use queries or links with location (#anchor) since your current url will become different from the one of the iframe source. So Instead of document.URL it's better to use [location.protocol, '//', location.host, location.pathname].join('') (Is there any method to get the URL without query string?)

In the parent document:

window.addEventListener('message',function(event) {

    if(event.origin !== 'https://example.com')
        return;

    // Parse message back to json
    var messageObject = JSON.parse(event.data);
    // Get event triggering iFrame
    var triggerFrame = $('iframe[src="'+messageObject.viewUrl+'"]');

 },false);

Each event will have to send the current iFrame URL to the parent document. We now can scan our documents for the iFrame with the given URL and work with it.

If some of you know a better way please post your answers.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top