Jak używasz window.postMessage w różnych domenach?

89

Wygląda na to, że celem window.postMessage jest umożliwienie bezpiecznej komunikacji między oknami / ramkami hostowanymi w różnych domenach, ale w rzeczywistości wydaje się, że nie pozwala na to w Chrome.

Oto scenariusz:

  1. Umieść element <iframe> (oznaczony literą srcw domenie B * ) na stronie w domenie A
  2. <iframe> kończy się głównie na tagu <script>, na końcu którego wykonanie ...
  3. Wzywam window.postMessage ( some_data , page_on_A )

Element <iframe> jest zdecydowanie w kontekście domeny B i potwierdziłem, że kod javascript osadzony w <iframe> działa poprawnie i wywołuje postMessagez poprawnymi wartościami.

W przeglądarce Chrome pojawia się ten komunikat o błędzie:

Nie można dodawać wiadomości do A . Odbiorca ma pochodzenie B .

Oto kod, który rejestruje odbiornik zdarzeń wiadomości na stronie A:

window.addEventListener(
  "message",
  function (event) {
    // Do something
  },
  false);

Próbowałem też dzwonić window.postMessage(some_data, '*'), ale wszystko, co robi, to wyeliminowanie błędu.

Czy po prostu nie mam tu sensu, czy window.postMessage (...) nie jest do tego przeznaczone? A może po prostu robię to strasznie źle?

* Tekst / html typu Mime, który musi pozostać.

Kevin Montrose
źródło
1
Prawdopodobnie już o tym wiesz, ale MDC ma doskonałe podsumowanie w postMessage: developer.mozilla.org/en/DOM/window.postMessage Oczywiście w przypadku implementacji FF, ale może jest tam coś, co wyjaśnia, dlaczego to nie działa.
Pekka,

Odpowiedzi:

79

Oto przykład, który działa w przeglądarce Chrome 5.0.375.125.

Strona B (zawartość iframe):

<html>
    <head></head>
    <body>
        <script>
            top.postMessage('hello', 'A');
        </script>
    </body>
</html>

Zwróć uwagę na użycie top.postMessagelub parent.postMessagenie window.postMessagetutaj

Strona A:

<html>
<head></head>
<body>
    <iframe src="B"></iframe>
    <script>
        window.addEventListener( "message",
          function (e) {
                if(e.origin !== 'B'){ return; } 
                alert(e.data);
          },
          false);
    </script>
</body>
</html>

A i B muszą być czymś podobnym http://domain.com

EDYTOWAĆ:

Z innym pytaniem , wygląda domen (A i B), tutaj musi mieć /dla postMessagedziałał poprawnie.

Mic
źródło
3
Gdy strona A sprawdza pochodzenie wiadomości, źródło to NIE będzie zawierało końcowego znaku „/”. Nie ma znaczenia, czy strona B zawiera na końcu znak „/”, czy nie. Inną rzeczą, na którą należy zwrócić uwagę, jest to, że adresy URL powinny być adresami bezwzględnymi.
Złap
1
Ta odpowiedź trochę mnie zdezorientowała i wciąż szukałem odpowiedzi. blog.teamtreehouse.com/cross-domain-messaging-with-postmessage zawiera bardzo dobre wyjaśnienie postMessage. Ważne jest, aby nadawca wiadomości znał domenę odbiorcy. W powyższym przykładzie A i B nie muszą być tymi samymi domenami, ale B musi dokładnie wiedzieć, z której domeny korzysta A.
Greg Bogumil
7
Pytanie dotyczy wielu domen. Zaakceptowana odpowiedź dotyczy tej samej domeny.
stackular
@stackular, niezupełnie. A i B mogą być dowolną domeną. To jest główny powód posiadaniapostMessage
Mic
1
+1. Chcemy potwierdzić, że to rozwiązanie zadziałało w naszym przypadku. Mamy stronę zawierającą element iframe z innej domeny . Należy pamiętać, że działa to tylko w przeglądarce Chrome, ponieważ w przeglądarce Firefox musimy użyć window.parent.postMessage zamiast top . Chociaż nie wiemy, czy można to zastosować w jakiejkolwiek innej przeglądarce.
rahmatns
24

Powinieneś wysłać wiadomość z ramki do rodzica, po załadowaniu.

skrypt ramki:

$(document).ready(function() {
    window.parent.postMessage("I'm loaded", "*");
});

I posłuchaj tego w rodzicu:

function listenMessage(msg) {
    alert(msg);
}

if (window.addEventListener) {
    window.addEventListener("message", listenMessage, false);
} else {
    window.attachEvent("onmessage", listenMessage);
}

Użyj tego linku, aby uzyskać więcej informacji: http://en.wikipedia.org/wiki/Web_Messaging

Golyo
źródło
2

Prawdopodobnie próbujesz wysłać swoje dane z mojadomena.com do www.mojadomena.com lub odwrotnie, UWAGA przegapiłeś „www”. http://mydomain.com i http://www.mydomain.com to inne domeny niż javascript.

Getoriks
źródło
2
W projekcie, który robię, używam file:/// Czy można uzyskać błędy domeny podczas pobierania treści wyłącznie z lokalnego systemu plików?
Jacksonkr,