Подтвердить что ты не робот

Перекрестный домен postMessage, укажите iFrame

Я использую postMessage для отправки событий из iframe в его родительский документ. У меня есть контроль над обеими сторонами, но контент поступает из двух разных доменов.

enter image description here

Моя простая проблема заключается в том, что я не могу определить iFrame внутри этого родительского метода обратного вызова. Реализация выглядит следующим образом:

В iFrame:

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

В родительском окне:

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);

Я хочу идентифицировать некоторый родительский элемент iframe, который (логически) внутри родительского документа.

Когда я пытаюсь использовать event.source.parentNode или некоторый jQuery для указанного объекта, Firefox говорит, я не могу этого сделать, чтобы предотвратить XSS, ошибка: Error: Permission denied to access property 'parentNode'

Как я могу получить родительский элемент iFrame, который вызвал прослушиватель событий postMessage?

4b9b3361

Ответ 1

для этого вы можете использовать имена окон, поскольку они передаются из тега iframe в контекст iframe.

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>

который предупреждает "fr2", затем "fr3". вы можете легко использовать имя, которое можно найти, чтобы найти iframe в родительской DOM, используя атрибуты CSS-селекторов.

иллюстративная демонстрация концепции window.name + iframe: http://pagedemos.com/namingframes/

этот мучительно простой подход также невосприимчив к вопросам, возникающим из-за одинаковых URL-адресов iframe.

Ответ 2

Как я понимаю, это может быть попытка здесь предположим, что ваш основной URL-адрес - www.abc.com\home.php

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

getOtherDomainContent.php в этом файле необходимо написать ajax-вызов, который получает содержимое перекрестного URL-адреса и нажимает этот контент в текущей части тела iframe (getOtherDomainContent.php).

getOtherDomainContent.php Код:

    <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>

Ответ 3

Как видно в этой теме: postMessage Source IFrame, можно сравнить каждый iframes contentWindow с event.source следующим образом:

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

Подсказка: Когда дело доходит до использования кросс-домена и iFrames, у вас нет доступа к атрибуту id или name iFrame внутри iFrame, поэтому мы не можем его получить.

Но мне это не очень понравилось. Мое решение на данный момент выглядит следующим образом:

В iFrame:

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

Update: docuent.URL может стать проблемой при использовании запросов или ссылок с местоположением (#anchor), так как ваш текущий url будет отличаться от источника iframe. Итак, вместо document.URL лучше использовать [location.protocol, '//', location.host, location.pathname].join('') (есть ли какой-либо метод для получения url без строки запроса в java script)

В родительском документе:

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);

Каждое событие должно отправить текущий URL-адрес iFrame в родительский документ. Теперь мы можем сканировать наши документы для iFrame с заданным URL-адресом и работать с ним.

Если кто-то из вас знает лучший способ, напишите ваши ответы.