Wie verwenden Sie window.postMessage domänenübergreifend?

87

Es scheint, als ob der Zweck von window.postMessage darin besteht, eine sichere Kommunikation zwischen Fenstern / Frames zu ermöglichen, die auf verschiedenen Domänen gehostet werden, aber dies scheint dies in Chrome nicht zuzulassen .

Hier ist das Szenario:

  1. Betten Sie einen <iframe> (mit einem srcauf Domäne B * ) in eine Seite auf Domäne A ein
  2. Der <iframe> ist meistens ein <script> -Tag, an dessen Ende die Ausführung erfolgt ...
  3. Ich rufe window.postMessage auf ( some_data , page_on_A )

Der <iframe> steht definitiv im Kontext von Domäne B, und ich habe bestätigt, dass das eingebettete Javascript in diesem <iframe> ordnungsgemäß ausgeführt wird und postMessagemit den richtigen Werten aufgerufen wird.

Ich erhalte diese Fehlermeldung in Chrome:

Nachricht kann nicht an A gesendet werden . Empfänger hat Ursprung B .

Hier ist der Code, der einen Listener für Nachrichtenereignisse auf der Seite auf A registriert:

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

Ich habe auch versucht anzurufen window.postMessage(some_data, '*'), aber alles was das tut, ist den Fehler zu unterdrücken.

Fehlt mir hier nur der Punkt, ist window.postMessage (...) nicht dafür gedacht? Oder mache ich es einfach schrecklich falsch?

* Mime-Typ Text / HTML, der es bleiben muss.

Kevin Montrose
quelle
1
Sie wissen das wahrscheinlich schon, aber MDC hat einen hervorragenden Überblick über postMessage: developer.mozilla.org/en/DOM/window.postMessage Für die FF-Implementierung natürlich, aber vielleicht gibt es dort etwas, das erklärt, warum es nicht funktioniert.
Pekka

Antworten:

79

Hier ist ein Beispiel, das unter Chrome 5.0.375.125 funktioniert.

Die Seite B (Iframe-Inhalt):

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

Beachten Sie die Verwendung von top.postMessageoder parent.postMessagenicht window.postMessagehier

Die Seite 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 und B müssen so etwas wie sein http://domain.com

BEARBEITEN:

Von einer anderen Frage , sieht es die Domänen (A und B hier) muss haben /für die postMessageordnungsgemäß funktioniert.

Mic
quelle
3
Wenn Seite A den Ursprung der Nachricht überprüft, enthält der Ursprung KEIN abschließendes '/'. Es scheint keine Rolle zu spielen, ob Seite B ein abschließendes '/' angibt oder nicht. Die andere Sache zu beachten ist, dass die URLs absolute URLs sein sollten.
Catch22
1
Diese Antwort hat mich ein bisschen verwirrt und immer noch auf der Suche nach einer Antwort. blog.teamtreehouse.com/cross-domain-messaging-with-postmessage enthält eine sehr gute Erklärung der postMessage. Wichtig ist, dass der Absender der Nachricht die Domäne des Empfängers kennt. Im obigen Beispiel müssen A und B nicht dieselben Domänen sein, aber B muss genau wissen, welche Domäne von A verwendet wird.
Greg Bogumil
7
Die Frage betrifft domänenübergreifend. Die akzeptierte Antwort bezieht sich auf dieselbe Domain.
Stapel
@stackular, nicht genau. A und B können beliebige Domänen sein. Das ist der Hauptgrund dafürpostMessage
Mic
1
+1. Wir möchten bestätigen, dass diese Lösung in unserem Fall funktioniert hat. Wir haben eine Seite, die einen Iframe aus einer anderen Domain enthält . Bitte beachten Sie, dass dies nur im Chrome-Browser funktioniert, da wir in Firefox window.parent.postMessage anstelle von top verwenden müssen . Wir wissen jedoch nicht, ob dies auf einen anderen Browser angewendet werden kann.
Rahmatns
24

Sie sollten nach dem Laden eine Nachricht vom Frame an das übergeordnete Element senden.

Rahmenskript:

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

Und hör es dir als Elternteil an:

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

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

Verwenden Sie diesen Link für weitere Informationen: http://en.wikipedia.org/wiki/Web_Messaging

Golyo
quelle
2

Wahrscheinlich versuchen Sie, Ihre Daten von mydomain.com an www.mydomain.com oder umgekehrt zu senden. HINWEIS Sie haben "www" verpasst. http://mydomain.com und http://www.mydomain.com sind andere Domänen als Javascript.

Getoriks
quelle
2
In einem Projekt, das ich verwende, verwende ich file:/// Ist es möglich, Domänenfehler zu erhalten, wenn Inhalte ausschließlich aus dem lokalen Dateisystem abgerufen werden?
Jacksonkr