Heim  >  Artikel  >  Web-Frontend  >  HTML5-domänenübergreifende Kommunikation postMessage

HTML5-domänenübergreifende Kommunikation postMessage

黄舟
黄舟Original
2017-02-16 14:30:481825Durchsuche

Verwendung von postMessage in der domänenübergreifenden HTML5-Kommunikation

Aus Sicherheitsgründen dürfen Dokumente unter verschiedenen Domänennamen nicht auf die Dokumente anderer zugreifen, aber Einige Manchmal ist es notwendig, dies zu tun. Daher können wir im Allgemeinen window.name, hash oder jsonp verwenden, um einen domänenübergreifenden Zugriff zu erreichen.

Seit der Veröffentlichung von HTML5 haben wir jedoch noch eine weitere Möglichkeit, postMessage zu implementieren. Das Folgende ist das einfachste Beispiel für Messaging. Die Funktion, die wir implementieren möchten, besteht darin, den Inhalt von Seite1 an eine andere Seite von Seite2 zu senden Geben Sie den Domänennamen ein, und dann zeigt Seite2 den entsprechenden Nachrichteninhalt an.

Im Folgenden sind einige wichtige Ereignisattribute aufgeführt:

  • Quelle – Nachrichtenquelle, Nachrichtensendefenster/Iframe.

  • Ursprung – URI der Nachrichtenquelle (kann Protokoll, Domänennamen und Port enthalten), der zur Überprüfung der Datenquelle verwendet wird.

  • Daten – die vom Sender an den Empfänger gesendeten Daten. <br>Diese drei Attribute sind Daten, die bei der Nachrichtenübertragung verwendet werden müssen.

Zuerst benötigen wir zwei Seiten, und dann müssen sie sich unter verschiedenen Domänennamen befinden. Natürlich muss dieser Computer über einen Webserver verfügen, um unterschiedliche zu erreichen Zugriff auf Domainnamen

127.0.0.1 www.postmessage1.com127.0.0.1 www.postmessage2.com

In der Homepage http://www.php.cn/ ist ein Iframe eingebettet

<!DOCTYPE html><html><head>
    <title>Html5 postMessage跨文档通信</title></head><body>
    <input type="text" id="text">
    <input type="button" id="send" value="发送">

    <iframe id="ifr" src="http://www.postmessage2.com/page2.html"></iframe>


    <script type="text/javascript">
        var text = document.getElementById(&#39;text&#39;),
            send = document.getElementById(&#39;send&#39;),
            ifr = window.frames[0];            //ifr = document.getElementById(&#39;ifr&#39;).contentWindow;
            //确保你使用的是iframe的contentWindow属性,而不是节点对象。

        send.addEventListener(&#39;click&#39;,function(){
            //主窗口postMessage发送消息给iframe子窗口。
            //子窗口通过监听message事件来获得消息
            ifr.postMessage(text.value,&#39;http://www.postmessage2.com&#39;);
        })    </script></body></html>

Die Quelladresse des Iframes lautet http:// www.php.cn/

<!DOCTYPE html><html><head>
    <title></title></head>
    <script type="text/javascript">
        //在iframe窗口中监听messages事件,并接收消息
        window.addEventListener(&#39;message&#39;,function(event){
            var p1 = document.getElementById(&#39;p1&#39;);            if(event.origin === &#39;http://www.postmessage1.com&#39;){
                p1.innerHTML += event.data +"<br>";
            }

        })    </script><body>
    <h1>我是一个iframe</h1>
    <p id="p1"></p></body></html>

HTML5-domänenübergreifende Kommunikation postMessage

Wie bei vielen anderen Webtechnologien wird die Verwendung dieser Technologie sehr gefährlich, wenn Sie die Gültigkeit der Datenquelle nicht überprüfen. Die Sicherheit Ihrer Anwendung erfordert, dass Sie dafür verantwortlich sind. window.postMessage ist wie PHP- versus JavaScript-Technologie. window.postMessage ist cool, nicht wahr?

Das Gleiche gilt für die bidirektionale Datenübertragung:

<!DOCTYPE html><html><head>
    <title>Html5 postMessage跨文档通信</title></head><body>
    <input type="text" id="text">
    <input type="button" id="send" value="发送">

    <iframe id="ifr" src="http://www.postmessage2.com/postmessage/iframe01.html"></iframe>


    <script type="text/javascript">
        var text = document.getElementById(&#39;text&#39;),
            send = document.getElementById(&#39;send&#39;),            // ifr = window.frames[0];
            ifr = document.getElementById(&#39;ifr&#39;).contentWindow;
        window.addEventListener(&#39;message&#39;, function(ev){
            if(ev.origin === &#39;http://www.postmessage2.com&#39;){
                alert(&#39;从&#39;+ ev.origin + &#39;传过来的消息:&#39; + ev.data);
            }
        });

        send.addEventListener(&#39;click&#39;,function(){
            //主窗口postMessage发送消息给iframe子窗口。
            //子窗口通过监听message事件来获得消息
            ifr.postMessage(text.value,&#39;http://www.postmessage2.com&#39;);
        })    </script></body></html>

Der Code für eine andere Seite lautet wie folgt:

<!DOCTYPE html><html><head>
    <title></title></head>
    <script type="text/javascript">
        //在iframe窗口中监听messages事件,并接收消息
        window.addEventListener(&#39;message&#39;,function(event){
            var p1 = document.getElementById(&#39;p1&#39;);            if (event.origin === &#39;http://www.postmessage1.com&#39;) {
                p1.innerHTML += "来自窗口" + event.origin + event.data+"<br>"
            }            //像主页面回送消息
            event.source.postMessage("你好,这里是:" + this.location, event.origin);

        });    </script><body>
    <h1>我是一个iframe</h1>
    <p id="p1"></p></body></html>

HTML5-domänenübergreifende Kommunikation postMessage

2. Kanalkommunikation

Nachrichtenkanäle bieten ein direktes, bidirektionales Kommunikationsmittel zwischen Browsing-Kontexten. Wie bei der dokumentübergreifenden Kommunikation wird das DOM nicht direkt verfügbar gemacht. Stattdessen ist jedes Ende der Pipe ein Port, und Daten werden von einem Port gesendet und vom anderen empfangen.

Nachrichtenkanäle sind nützlich, insbesondere für die Kommunikation über mehrere Ursprünge hinweg. Bitte berücksichtigen Sie die folgende Situation: <br>Renren.com (http://www.php.cn/) bettet gleichzeitig eine Spieleseite eines Drittanbieters ein (über iframe, z. B. „Renren Restaurant“) -party Die Spieleseite (http://www.php.cn/) muss die Kommunikationsinformationen des Benutzers von einer anderen Adressbuch-Website (http://www.php.cn/) abrufen. Was zu tun?

Das heißt, die Adressbuchseite muss Informationen an die Spieleseite senden. Gemäß der dokumentübergreifenden Kommunikation lassen wir die übergeordnete Seite als Proxy dienen (hier die Renren-Seite). ähnlich der ersten Demo). Dieser Ansatz bedeutet jedoch, dass Adressbuchseiten das gleiche Maß an Vertrauen haben müssen wie Renren-Seiten. Renren, eine Social-Networking-Site, muss jeder Anfrage vertrauen oder sie für uns filtern (sollte sich beziehen auf: einzeln angeben).

Durch die Kanalkommunikation können die Adressbuch-Site (http://www.php.cn/) und die Spiele-Site (http://www.php.cn/) jedoch direkt kommunizieren .

MessageChannel- und MessagePort-Objekte

Wenn wir ein MessageChannel-Objekt erstellen, erstellen wir tatsächlich zwei miteinander verbundene Ports. Für die sendende Seite bleibt ein Port offen. Der andere wird an andere Browsing-Kontexte weitergeleitet (von der übergeordneten Seite an eine andere untergeordnete Seite des iframe-Elements gesendet).

var mc = new MessageChannel();

Jeder Port ist ein MessagePort-Objekt, einschließlich 3 verfügbarer Methoden:

  • postMessage() sendet eine Nachricht über den Kanal

  • start() Versenden empfangener Nachrichten auf dem Port starten

  • close() Port schließen

Das MessagePort-Objekt verfügt auch über die onmessage-Ereigniseigenschaften, die zum Definieren von Ereignishandlern anstelle von Ereignis-Listenern verwendet werden können.

Beispiele <br>Ich kann den Fachjargon oben nicht einmal verstehen, aber es ist einfacher, anhand von Beispielen darüber zu sprechen.

Erstellen Sie zunächst drei Websites, die Hauptwebsite ist: http://www.php.cn/ und zwei Unterwebsites: http://www.php.cn/ und http://www.php .cn/. Simulieren Sie nun den Kommunikationsprozess zwischen zwei Unterwebsites:

Anforderung: Wenn Unterwebsite 1 geladen ist, senden Sie eine Nachricht an Unterwebsite 2: „(1) Ich kann es kaum erwarten, geht es dir gut?“ ? <br>“, wenn Sub-Website 2 die Nachricht empfängt, gibt sie die Meldung „(2) Keine Sorge, es wird bald fertig sein!“ Wenn Unterwebsite 1 die Nachricht von Unterwebsite 2 empfängt, werden die Dialoginformationen an die Hauptseite zurückgegeben.

Code der Unterseite 1

<!DOCTYPE html><html><head>
    <title>通道通信子页面iframe01</title></head><body><script type="text/javascript">
    window.onload = function(){
        var mc, portMessageHandler;
        mc = new MessageChannel();
        portMessageHandler = function(event){
            alert(event.data);
        }        //向父页面发送消息以及端口port2
        window.parent.postMessage(&#39;(1)我已经等不及了,你好了吗?<br>&#39;, &#39;http://localhost/test1/main.html&#39;, [mc.port2]);        //定义本页面接收到消息后,应该做的处理
        mc.port1.addEventListener(&#39;message&#39;, portMessageHandler, false);        //打开本页面的端口,开始监听。。。
        mc.port1.start();
    }</script></body></html>

Code der Hauptseite:

<!DOCTYPE html><html><head>
    <title>messageChannel通信</title></head><body>
    <h1>通道通信实例</h1>

    <iframe style="display: none;" src="http://localhost/test1/iframe01.html"></iframe>
    <iframe style="display: none;" src="http://localhost/test2/iframe02.html"></iframe>
    <script type="text/javascript">
        window.onload = function(){
            var iframes, messageHandle;
            iframes = window.frames;

            messageHandle = function(event){
                if (event.ports.length > 0) {                    //如果有接收端口,将接收的端口与消息转发给iframe02
                    iframes[1].postMessage(event.data,&#39;http://localhost/test2/iframe02.html&#39;, event.ports);
                }
            }            //监听第一个页面
            window.addEventListener(&#39;message&#39;,messageHandle,false);
        }    </script></body></html>

Code der Unterseite 2:

<!DOCTYPE html><html><head>
    <title>通道通信子页面iframe02</title></head><body><script type="text/javascript">
    window.onload = function(){
        var messageHandler = function(event){
            event.ports[0].postMessage(event.data + "(2)你别急呀,马上就好!");
        }        //子页面2接收到消息,并将新的消息转发给子页面1
        window.addEventListener(&#39;message&#39;,messageHandler, false);
    }</script></body></html>

Ergebnisbild<br>HTML5-domänenübergreifende Kommunikation postMessage

Die obige Demo verwendet drei Seiten: die Hauptseite und zwei Iframe-Seiten. Lassen Sie uns darüber sprechen, was jede Seite tut:

Die erste ist die erste Iframe-Seite: Sie hat drei Aufgaben,

  • 一是创建MessageChannel通道对象;

  • 二是告诉主页面,我加载好了,并把端口传过去;

  • 三是显示发送信息。

//1.创建MessageChannel通道对象mc = new MessageChannel();//2.二是告诉主页面,我加载好了,并把端口传过去;window.parent.postMessage(&#39;(1)我已经等不及了,你好了吗?<br>&#39;, &#39;http://localhost/test1/main.html&#39;, [mc.port2]);//3.显示发送信息mc.port1.addEventListener(&#39;message&#39;, portMessageHandler, false);
mc.port1.start();

主页面其任务很简单就一个:告诉第二个iframe页面,端口已经打开了(第一个iframe就可以确定跟第二个iframe通信的端口了)。

// 将端口告诉其他文档iframes[1].postMessage(event.data,&#39;http://localhost/test2/iframe02.html&#39;, event.ports);

最后就是第二个iframe页面。其任务有两个:一是确定接到的消息与端口;二是将post一个新的数据和此端口保持通信了。

// 1. 接到消息与端口window.addEventListener(&#39;message&#39;,messageHandler, false);// 2. 与端口建立通道,post一个新的数据port.postMessage(message);

html5跨域通信之postMessage的用法

不同域名下的文档因为安全问题,不允许相互之间文档的访问,但是有的时候却不得不需要这样的操作。因此我们一般可以采用 window.name,hash,或者jsonp来实现跨域访问。

不过自从html5出来以后,我们又可以多一种实现方式了postMessage,下面就是一个最简单的消息传递的例子,我们要实现的功能是将page1页面中的内容,发送到不同域名下的page2页面,然后page2将对应消息内容展示出来。

下面是几个比较重要的事件属性:

  • source – 消息源,消息的发送窗口/iframe。

  • origin – 消息源的URI(可能包含协议、域名和端口),用来验证数据源。

  • data – 发送方发送给接收方的数据。 <br>这三个属性是消息传输中必须用到的数据。

首先我们需要两个页面,然后必须分别位于不同的域名下,当然本机肯定要有一个web服务器,接下来就通过修改host来实现不同域名访问

127.0.0.1 www.postmessage1.com127.0.0.1 www.postmessage2.com

主页http://www.php.cn/ 里面嵌套一个iframe框架

<!DOCTYPE html><html><head>
    <title>Html5 postMessage跨文档通信</title></head><body>
    <input type="text" id="text">
    <input type="button" id="send" value="发送">

    <iframe id="ifr" src="http://www.postmessage2.com/page2.html"></iframe>


    <script type="text/javascript">
        var text = document.getElementById(&#39;text&#39;),
            send = document.getElementById(&#39;send&#39;),
            ifr = window.frames[0];            //ifr = document.getElementById(&#39;ifr&#39;).contentWindow;
            //确保你使用的是iframe的contentWindow属性,而不是节点对象。

        send.addEventListener(&#39;click&#39;,function(){
            //主窗口postMessage发送消息给iframe子窗口。
            //子窗口通过监听message事件来获得消息
            ifr.postMessage(text.value,&#39;http://www.postmessage2.com&#39;);
        })    </script></body></html>

iframe框架的src地址为http://www.php.cn/

<!DOCTYPE html><html><head>
    <title></title></head>
    <script type="text/javascript">
        //在iframe窗口中监听messages事件,并接收消息
        window.addEventListener(&#39;message&#39;,function(event){
            var p1 = document.getElementById(&#39;p1&#39;);            if(event.origin === &#39;http://www.postmessage1.com&#39;){
                p1.innerHTML += event.data +"<br>";
            }

        })    </script><body>
    <h1>我是一个iframe</h1>
    <p id="p1"></p></body></html>

HTML5-domänenübergreifende Kommunikation postMessage

跟其他很web技术一样,如果你不校验数据源的合法性,那使用这种技术将会变得很危险;你的应用的安全需要你对它负责。window.postMessage就像是PHP相对于JavaScript技术。window.postMessage很酷,不是吗?

双向数据传输也是一样的:

<!DOCTYPE html><html><head>
    <title>Html5 postMessage跨文档通信</title></head><body>
    <input type="text" id="text">
    <input type="button" id="send" value="发送">

    <iframe id="ifr" src="http://www.postmessage2.com/postmessage/iframe01.html"></iframe>


    <script type="text/javascript">
        var text = document.getElementById(&#39;text&#39;),
            send = document.getElementById(&#39;send&#39;),            // ifr = window.frames[0];
            ifr = document.getElementById(&#39;ifr&#39;).contentWindow;
        window.addEventListener(&#39;message&#39;, function(ev){
            if(ev.origin === &#39;http://www.postmessage2.com&#39;){
                alert(&#39;从&#39;+ ev.origin + &#39;传过来的消息:&#39; + ev.data);
            }
        });

        send.addEventListener(&#39;click&#39;,function(){
            //主窗口postMessage发送消息给iframe子窗口。
            //子窗口通过监听message事件来获得消息
            ifr.postMessage(text.value,&#39;http://www.postmessage2.com&#39;);
        })    </script></body></html>

另一个页面的代码如下:

<!DOCTYPE html><html><head>
    <title></title></head>
    <script type="text/javascript">
        //在iframe窗口中监听messages事件,并接收消息
        window.addEventListener(&#39;message&#39;,function(event){
            var p1 = document.getElementById(&#39;p1&#39;);            if (event.origin === &#39;http://www.postmessage1.com&#39;) {
                p1.innerHTML += "来自窗口" + event.origin + event.data+"<br>"
            }            //像主页面回送消息
            event.source.postMessage("你好,这里是:" + this.location, event.origin);

        });    </script><body>
    <h1>我是一个iframe</h1>
    <p id="p1"></p></body></html>

HTML5-domänenübergreifende Kommunikation postMessage

2.通道通信

消息通道提供了一个直接,双向浏览上下文之间的通信手段。跟跨文档通信一样,DOM不直接暴露。取而代之,管道每端为端口,数据从一个端口发送,被另一个端口接收,。

消息通道是有用的,特别是跨多个起源的沟通。请考虑以下情形: <br>人人网上(http://www.php.cn/)嵌入了一个第三方的游戏页面(通过iframe的形式,如“人人餐厅”),同时,这个第三方的游戏页面(http://www.php.cn/)又需要从另外一个通讯录网站(http://www.php.cn/)获取用户的通讯信息。咋办?

也就是说通讯录站点要发送信息给游戏站点,根据跨文档通信,我们让父页面作为代理(也就是这里的人人网页面)(类似第一个demo)。然而,这种做法意味着通讯录站点需要有和人人网页面一样的信任级别。人人网这个社交站点需要信任每一个请求,或者为我们过滤(应该指:一个一个指定)。

但是,使用通道通信,通讯录站点(http://www.php.cn/)和游戏站点(http://www.php.cn/)可以直接沟通

MessageChannel和MessagePort对象

当我们创建了一个MessageChannel对象,我们实际上创造了两个相互关联的端口。一个端口保持开放,为发送端。另外一个被转发到其他浏览上下文(被父页面发送到另外一个iframe元素的子页面中)。

var mc = new MessageChannel();

每一个端口就是一个MessagePort对象,包含3个可用方法:

  • postMessage() 通过通道发送消息

  • start()   开始在端口上分派接受的信息

  • close()   关闭端口

MessagePort对象还有onmessage事件属性,可被用来定义事件句柄而不是事件监听。

实例 <br>上面过于术语的东西我自己都看不明白,还是实例好说话。

首先建立三个网站,其中主网站为:http://www.php.cn/,另外建立两个子网站http://www.php.cn/和http://www.php.cn/。现在来模拟两个子网站之间的通信过程:

需求:当子网站1被加载完成后,向子网站2发送消息:“(1)我已经等不及了,你好了吗?<br>”,当子网站2接收到消息后,向子网站1返回消息,“(2)你别急呀,马上就好!”。当子网页1接收到子网站2 的消息后,返回给主页面页面对话信息.

子页面1的代码

<!DOCTYPE html><html><head>
    <title>通道通信子页面iframe01</title></head><body><script type="text/javascript">
    window.onload = function(){
        var mc, portMessageHandler;
        mc = new MessageChannel();
        portMessageHandler = function(event){
            alert(event.data);
        }        //向父页面发送消息以及端口port2
        window.parent.postMessage(&#39;(1)我已经等不及了,你好了吗?<br>&#39;, &#39;http://localhost/test1/main.html&#39;, [mc.port2]);        //定义本页面接收到消息后,应该做的处理
        mc.port1.addEventListener(&#39;message&#39;, portMessageHandler, false);        //打开本页面的端口,开始监听。。。
        mc.port1.start();
    }</script></body></html>

主页面的代码:

<!DOCTYPE html><html><head>
    <title>messageChannel通信</title></head><body>
    <h1>通道通信实例</h1>

    <iframe style="display: none;" src="http://localhost/test1/iframe01.html"></iframe>
    <iframe style="display: none;" src="http://localhost/test2/iframe02.html"></iframe>
    <script type="text/javascript">
        window.onload = function(){
            var iframes, messageHandle;
            iframes = window.frames;

            messageHandle = function(event){
                if (event.ports.length > 0) {                    //如果有接收端口,将接收的端口与消息转发给iframe02
                    iframes[1].postMessage(event.data,&#39;http://localhost/test2/iframe02.html&#39;, event.ports);
                }
            }            //监听第一个页面
            window.addEventListener(&#39;message&#39;,messageHandle,false);
        }    </script></body></html>

子页面2的代码:

<!DOCTYPE html><html><head>
    <title>通道通信子页面iframe02</title></head><body><script type="text/javascript">
    window.onload = function(){
        var messageHandler = function(event){
            event.ports[0].postMessage(event.data + "(2)你别急呀,马上就好!");
        }        //子页面2接收到消息,并将新的消息转发给子页面1
        window.addEventListener(&#39;message&#39;,messageHandler, false);
    }</script></body></html>

结果图 <br>HTML5-domänenübergreifende Kommunikation postMessage

上面的demo动用了三个页面:主页面和两个iframe页面。下面说说每个页面都做了些什么:

首先是第一个iframe页面:其任务有三个,

  • 一是创建MessageChannel通道对象;

  • 二是告诉主页面,我加载好了,并把端口传过去;

  • 三是显示发送信息。

//1.创建MessageChannel通道对象mc = new MessageChannel();//2.二是告诉主页面,我加载好了,并把端口传过去;window.parent.postMessage(&#39;(1)我已经等不及了,你好了吗?<br>&#39;, &#39;http://localhost/test1/main.html&#39;, [mc.port2]);//3.显示发送信息mc.port1.addEventListener(&#39;message&#39;, portMessageHandler, false);
mc.port1.start();

主页面其任务很简单就一个:告诉第二个iframe页面,端口已经打开了(第一个iframe就可以确定跟第二个iframe通信的端口了)。

// 将端口告诉其他文档iframes[1].postMessage(event.data,&#39;http://localhost/test2/iframe02.html&#39;, event.ports);

最后就是第二个iframe页面。其任务有两个:一是确定接到的消息与端口;二是将post一个新的数据和此端口保持通信了。

// 1. 接到消息与端口window.addEventListener(&#39;message&#39;,messageHandler, false);// 2. 与端口建立通道,post一个新的数据port.postMessage(message);

 以上就是html5跨域通信之postMessage的内容,更多相关内容请关注PHP中文网(www.php.cn)!<br>

<br>

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn