web-dev-qa-db-fra.com

Permettre à un enfant Iframe d'appeler une fonction sur sa fenêtre parente à partir d'un autre domaine

J'ai créé une page qui est chargée dans un IFrame et qui doit appeler une fonction sur la page parente une fois le chargement terminé.

Cela fonctionne localement en développement (sur le même domaine) mais dans le monde réel, il est hébergé sur un domaine complètement différent, donc je rencontre évidemment des problèmes de domaine croisé, à savoir:

Tentative JavaScript non sécuritaire d'accès au cadre avec l'URL http: // [...] site1.com à partir du cadre avec l'URL http: // [...] site2.com/iframe. Les domaines, les protocoles et les ports doivent correspondre.

Je contrôle les deux serveurs, alors est-il possible que je mette quelque chose sur l'un des serveurs ou sur les deux qui dit qu'ils sont autorisés à se parler? 

J'ai examiné la définition de "document.domain" à la fois dans la page Iframe et dans la page parent.

J'ai essayé de définir l'en-tête de contrôle d'accès:

en-tête ('Access-Control-Allow-Origin: *');

Mais ni l'un ni l'autre ne fonctionne.

Existe-t-il un moyen d'autoriser un Iframe à appeler une fonction dans la fenêtre Parent d'un domaine complètement différent lorsque je contrôle les deux serveurs?

23
Brett

Vous pouvez communiquer entre les cadres via l'API de publication message .

Par exemple, dans votre cadre enfant, vous pouvez appeler:

parent.postMessage("child frame", "*");

Et dans le cadre parent, enregistrez un gestionnaire de messages:

window.addEventListener("message", function(event) {
    console.log("Hello from " + event.data);
});
76
dfreeman
4
iivel

Ce problème peut être facilement résolu en utilisant un .htaccess rewrite. 

Démo:

A. Créez un répertoire nommé "iframeContent /" sur le serveur 1.

B. Placez dans ce répertoire un fichier nommé index.php contenant:

<html> 
<head></head> 
<body>

<script type="text/javascript">

    parent.check();

</script>

</body> 
</html>

C'est le contenu de l'iFrame. Il appellera une fonction dans un parent.

C. Créez un répertoire nommé "iframeTesting_without-htaccess /" sur le serveur 2.

D. Placez dans ce répertoire un fichier nommé index.php contenant: 

<html> 
<head></head> 
<body>

<script type="text/javascript">

    function check() { 

       alert("hello");

    }

</script>

<iframe id="sidebnrId" name="sidebnr"
src="PATH-ON-SERVER-1/iframeContent/" frameborder="0"
height="500px" width="600px" scrolling="no"></iframe>

</script>

</body> 
</html>

Ceci est simplement le contenu des fenêtres parentes. Notez simplement que le contenu iFrame se trouve sur un autre serveur (car sur le serveur 1).

E. Accédez à "PATH-ON-SERVER-2/iframeTesting_without-htaccess /" avec un navigateur Web -> rien ne se passe: l’iframe n’a pas accès à la fonction de son parent.

ICI IS COMMENT RÉSOUDRE LE PROBLÈME

F. Créez un autre répertoire nommé "iframeTesting_with-htaccess /" sur le serveur 2.

G. Placez dans ce répertoire un fichier nommé index.php contenant: 

<html> 
<head></head> 
<body>

<script type="text/javascript">

    function check() { 

       alert("hello");

    }

</script>

<iframe id="sidebnrId" name="sidebnr"
src="content-iframe/" frameborder="0"
height="500px" width="600px" scrolling="no"></iframe>

</script>

</body> 
</html>

Cette fois, l’iFrame ne pointe plus directement sur le contenu de SERVER 1, mais sur un répertoire fictif intermédiaire "content-iframe /" situé sur le même serveur (SERVER 2).

H. Placez dans ce répertoire un fichier .htaccess contenant: 

Options +FollowSymLinks
RewriteEngine On

RewriteBase /

RewriteRule ^content-iframe/$ PATH-ON-SERVER-1/iframeContent/ [R,NC,P]

Le rôle de ce fichier est de rediriger tout accès au répertoire fictif vers le contenu du serveur 1.

I. Essayez à nouveau, accédez à "PATH-ON-SERVER-2/iframeTesting_with-htaccess /" avec un navigateur Web. Cette fois, ça va marcher. J'espère que ça a aidé :-)

2
Gilbou

Dans les navigateurs modernes, vous pouvez utiliser window.postMessage() pour communiquer entre des cadres coopérants de différents domaines. Vous ne pouvez pas appeler une fonction directement, mais vous pouvez transmettre des données ou des messages entre les deux. Voir le description sur MDN .

1
jfriend00