XDM-跨文档消息传送

XDM

cross-document messaging 类似于XSS的简称,故称为 XDM 而不是 CDM

某些时候 XDM 也能作为跨域的实现手段之一

与Jsonp 和 传统的 CORS 跨域方式不同

XDM通常用于不同域的页面之间传递消息

 

postMessage

postMessage() 方法作为 XDM 的核心被添加进了 HTML5 规范中

该方法的作用是:向当前页面的iframe或者弹出的窗口传递消息

 

该方法用于接收以下两个参数:

  1. 消息的内容
  2. 接收消息的域

 

通过第二个参数可以防止浏览器将信息发送到不安全的地方

使用方法如下:

// 支持XDM的浏览器也支持 iframe 的 contentWindow属性
let iframeWindow = document.getElementById("myframe").contentWindow;
iframeWindow.postMessage("这里是消息","http://www.example.com");

上方的postMessage的第二个参数则用于指定接收消息的文档的源域

如果匹配,则将消息传入内嵌框架中,否则什么也不做

当然该参数也可以设置为"*" 表示所有域都可以接受消息

 

发送消息介绍完了,自然就需要接收传递的信息

 

当文档接收到 XDM消息时就会触发 window 对象的 message 事件

该事件是以异步形式触发的所以可能存在时延, 触发该事件后,该事件的事件对象(event)会包含以下信息:

  • data: postMessage传入的第一个参数字符串数据
  • origin: 发送消息文档的所在的域
  • source: 发送消息文档的window对象的代理,用于在发送上一条消息的窗口中调用postMessage方法(即发送回执消息)

就像发送时指定消息接收的域一样,收到消息后验证消息的来源域也同样重要,以此保证消息来自已知的域

基本的验证如下:

window.onmessage = function(event){
    // 确保消息来源于已知域
    if(evnet.origin == "http://www.example.com"){
        // 处理接收的数据
        processMessage(evnet.data);

        // 可选,向来源窗口发送回执
        event.source.postMessage("Received","http://example1.com");
    }
}

需要注意的是:

evnet.source 大多数情况下只是 window 对象的代理对象,也就是说并不是真正的 window 对象

所以不能通过该代理对象来访问原本 window 对象上的属性和值

 

XDM的一个怪异之处在于:

postMessage的第一个参数最早是作为永远都是字符串来实现的,但后来允许传入任何数据结构,但是为了保险起见最好还是只传入字符串,如果希望传入json数据最好使用 JSON.stringify() 来处理

圈起来上面的是要考的,在阿里面前端的时候被问到,当时是蒙逼且绝望的emm....

 

最后就是这种跨域的浏览器兼容情况了,话不多说直接上图,自己感受

XDM-跨文档消息传送

 

上一篇:HTML5从iFrame调用父JavaScript函数的方法 – 除了使用postMessage之外?或PhoneGap应用程序的解决方案?


下一篇:iframe基于postMessage实现跨域通信