用postMessage实现跨域通信

     出于要打造一个各个web应用间能够相互联系的生态系统的目标,则需要一种在各个窗口间安全发送消息的方式,利用postMessage()开发正是这样一种方式。


     曾经很长一段时间以来,只有遵守相同协议,并且具有相同端口号,同时在一个主机这样的条件下,窗口间才能互发消息。postMessage()提供了一种安全的跨域通信方法,从而打破了这样的限制。


     在这篇文章中你将首先学习如何利用postMessage()实现分别处在不同域下的两个窗口之间的通信,其中一个窗口是控制窗口(controller window),另一个是接收窗口(receiver window )。


postMessage()来发送消息

postMessage()接收两个参数:

        1、 message——即将被发送到接收窗口的字符串或者对象。
        2、targetOrigin ——接收窗口的URL。为能实现消息的成功发送,目标窗口的协议名,端口号以及主机名必须匹配。“*”能够匹配任何URL,为安全考虑,我们不鼓励这么做。

      如果一个窗口(控制窗口)想向其他窗口(接收窗口)发送消息,则控制窗口可以调用这个方法。我们可以用多种不同方法获得目标窗口的引用。

         1、  使用window.open()方法将返回一个新窗口的引用;
         2、  对iframes而言,可以使用iframes的contentWindow属性。
 
targetWindow.postMessage('Hello World!', 'http://example.com');


        下面让我们来研究下如何在接收窗口上接收信息。

添加事件监听器来接收消息


       当调用postMessage()执行成功后,接收窗口上的MessageEvent事件即被触发。你可以用一个标准的事件监听器来监听这个事件并执行一些代码。

      传入监听器回调的事件有项属性data,能够用来获取由postMessage传入的string或者object。

window.addEventListener('message', function(e) {
  var message = e.data;
});


示例:与iframe通信

                            

                                                                                             使用postMessage与iframe进行通信

        现在你已经掌握了如何使用postMessage()在不同窗口间传递消息,下面让我来看一个例子。

在这个部分我们将在代码层面讲述通过一个示例演示控制页面如何与利用iframe嵌套在其中的接收页面进行通信的。

查看示例              下载代码                   在codepen上查看  



控制窗口


       首先我们需要为控制页面写一些html,其中的主要元素有一个是<button>,用来发送消息。另外一个是个<iframe>,用来展示嵌套的接收页面(发布在另外一个域上)
<h1>Controller Window</h1>
<p>
  This document is on the domain: http://codepen.io
</p>
<p>
  <button id="send">Send Message</button>
</p>


<iframe id="receiver" src="http://demos.matt-west.com/post-message/receiver.html" width="500" height="200">
  <p>Your browser does not support iframes.</p>
</iframe>


      回到控制页面的JS代码上来,第一件事情是获得一个接收窗口的引用receiver,然后取得另外一个按钮的引用btn
      接着我们需要写一个方法来处理发送消息的过程,当点击“Send Message”按钮时将调用这个方法。在这个方法中我们调用receiver变量的postMessage() 方法,并将'Hello Treehouse!'作为我们传递的信息。接收页面部署在http://demos.matt-west.com上,所以我们将此URL拿来用作targetOrigin参数。


      最后我们在btn上建立一个事件监听器,当点击这个按钮时,sendMessage()方法将被调用 。

window.onload = function() {
  // Get the window displayed in the iframe.
  var receiver = document.getElementById('receiver').contentWindow;

  // Get a reference to the 'Send Message' button.
  var btn = document.getElementById('send');

  // A function to handle sending messages.
  function sendMessage(e) {
    // Prevent any default browser behaviour.
    e.preventDefault();

    // Send a message with the text 'Hello Treehouse!' to the receiver window.
    receiver.postMessage('Hello Treehouse!', 'http://demos.matt-west.com');
  }

  // Add an event listener that will execute the sendMessage() function
  // when the send button is clicked.
  btn.addEventListener('click', sendMessage);
}

      以上是控制页面需要做的所有事,下面让我来分析下接收页面部分的代码。


接收窗口

      接收窗口的html代码非常基础。唯一一个重要的元素是id号是message<div>,用来显示传递到窗口的信息。
<h1>Receiver Window</h1>
<p>
  This document is on the domain: http://demos.matt-west.com
</p>
<div id="message"></div>


      在JS代码中我们首先得获得<div>元素的引用。

      接着,我们创建一个方法receiveMessage,当窗口接收到消息时该方法将被调用。在这个方法的内部我们首先检查消息确保其来自http://s.codepen.io(控制页面的域)。任何网站都能够传递消息到你的页面所以在执行代码前,你得首先检查信息的源。通过检查事件的origin属性我们能获得源。然后我们能够从data属性中获取信息,并通过messageEle来更新内容。

      最后,我们设置一个事件监听器,当message触发时,我们将来执行receiveMessage()方法。

window.onload = function() {
  // Get a reference to the div on the page that will display the
  // message text.
  var messageEle = document.getElementById('message');


  // A function to process messages received by the window.
  function receiveMessage(e) {
    // Check to make sure that this message came from the correct domain.
    if (e.origin !== "http://s.codepen.io")
      return;


    // Update the div element to display the message.
    messageEle.innerHTML = "Message Received: " + e.data;
  }


  // Setup an event listener that calls receiveMessage() when the window
  // receives a new MessageEvent.
  window.addEventListener('message', receiveMessage);
}

      当你运行这个demo后,你会发现,当你点击“send message”按钮时Hello Treehouse!将被显示在iframe内部。


postMessage的浏览器支持

      浏览器支持postMessage有段时间了,IE自IE8后支持postMessage,但是IE8和IE9仅支持使用postMessage在document和iframe间通信,跨窗口跨tab的支持要到IE10才支持


IE FIREFOX CHROME SAFARI OPERA
8+ 3.0+ 1.0+ 4.0+ 9.5+

总结
      本文你学习了如何使用postMessage实现网页间的跨域通信。当使用postMessage时一些安全问题值得留意。首先你得具体化targetOrigin的URL,而不要仅仅使用*,否则你可能不经意发送信息到了一些事先不知道的网站。检查发送来的信息的源也是一种保证网页安全的措施。

      当我们使用iframe时,postMessage是唾手可得的工具。


原文链接:http://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值