Comment utilisez-vous window.postMessage sur plusieurs domaines?

89

Il semble que le but de window.postMessage soit de permettre une communication sécurisée entre les fenêtres / cadres hébergés sur différents domaines, mais il ne semble pas le permettre dans Chrome.

Voici le scénario:

  1. Incorporer un <iframe> (avec un srcsur le domaine B * ) dans une page du domaine A
  2. Le <iframe> finit par être principalement une balise <script>, à la fin de l'exécution de laquelle ...
  3. J'appelle window.postMessage ( some_data , page_on_A )

Le <iframe> est très certainement dans le contexte du domaine B, et j'ai confirmé que le javascript intégré dans ce <iframe> s'exécute correctement et appelle postMessageavec les valeurs correctes.

Je reçois ce message d'erreur dans Chrome:

Impossible de poster un message à A . Bénéficiaire a l' origine B .

Voici le code qui enregistre un écouteur d'événement de message dans la page sur A:

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

J'ai également essayé d'appeler window.postMessage(some_data, '*'), mais tout ce que cela fait est de supprimer l'erreur.

Suis-je juste en train de manquer le point ici, window.postMessage (...) n'est-il pas destiné à cela? Ou est-ce que je le fais horriblement mal?

* Texte de type Mime / html, qu'il doit rester.

Kevin Montrose
la source
1
Vous en êtes probablement déjà conscient, mais MDC a un excellent récapitulatif sur postMessage: developer.mozilla.org/en/DOM/window.postMessage Pour l'implémentation de FF évidemment, mais peut-être qu'il y a là quelque chose qui explique pourquoi cela ne fonctionne pas.
Pekka

Réponses:

79

Voici un exemple qui fonctionne sur Chrome 5.0.375.125.

La page B (contenu iframe):

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

Notez l'utilisation top.postMessageou parent.postMessagepas window.postMessageici

La page 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 et B doivent être quelque chose comme http://domain.com

ÉDITER:

À partir d' une autre question , il semble que les domaines (A et B ici) doivent avoir un /pour que le postMessagefonctionne correctement.

Micro
la source
3
Lorsque la page A vérifie l'origine du message, l'origine ne contiendra PAS de «/» à la fin. Il ne semble pas important que la page B spécifie un «/» de fin ou non. L'autre chose à noter est que les URL doivent être des URL absolues.
Catch
1
Cette réponse m'a laissé un peu confus et toujours à la recherche d'une réponse. blog.teamtreehouse.com/cross-domain-messaging-with-postmessage contient une très bonne explication du postMessage. Ce qui est important, c'est que l'expéditeur du message connaisse le domaine du destinataire. Dans l'exemple ci-dessus, A et B ne doivent pas nécessairement être les mêmes domaines, mais B doit savoir exactement quel domaine est utilisé par A.
Greg Bogumil
7
La question concerne le cross-domain. La réponse acceptée concerne le même domaine.
stackular
@stackular, pas exactement. A et B peuvent être n'importe quel domaine. C'est la raison principale d'avoirpostMessage
Mic
1
+1. Nous voulons confirmer que cette solution a fonctionné sur notre cas. Nous avons une page qui contient un iframe d'un domaine différent . Veuillez noter que cela ne fonctionne que dans le navigateur Chrome, car dans Firefox, nous devons utiliser window.parent.postMessage au lieu de top . Bien que nous ne sachions pas si cela peut être appliqué à un autre navigateur.
rahmatns le
24

Vous devez publier un message du cadre au parent, après le chargement.

script de trame:

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

Et écoutez-le en parent:

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

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

Utilisez ce lien pour plus d'informations: http://en.wikipedia.org/wiki/Web_Messaging

Golyo
la source
2

Vous essayez probablement d'envoyer vos données de mydomain.com à www.mondomaine.com ou inversement, REMARQUE vous avez manqué "www". http://mondomaine.com et http://www.mydomaine.com sont des domaines différents de javascript.

Getoriks
la source
2
Dans un projet que je fais, j'utilise file:/// Est-il possible d'obtenir des erreurs de domaine lors de l'extraction de contenu uniquement à partir du système de fichiers local?
Jacksonkr