html5 跨文档通讯 - html5 详细教程
html5 跨文档通讯
版本:HTML5
对窗口对象的message事件进行监听,使用window对象的postMessage()方法向其他窗口发送消息。
跨文档消息传送(cross-document messaging),简称XDM,指的是来自不同域的页面间传递消息。
XDM的核心是postMessage()方法。目的:向另一个地方传递数据。对于XDM而言,“另一个地方”指的是包含在当前页面中的元素,或者由当前页面弹出的窗口。
postMessage()
方法接收两个参数:一条消息和一个表示消息接收方来自哪个域的字符串。第二个参数对保障安全通信非常重要,可以防止浏览器把消息发送到不安全的地方。
接收到XDM消息时,会触发window对象的message
事件。这个事件是以异步形式触发的,因此从发送消息到接受消息(触发接受窗口的message事件)可能要经过一段时间的延迟。
有了XDM,包含的页面可以确保自身不受恶意内容的侵扰,因为它只通过XDM为嵌入的框架通信。而XDM也可以来自相同域的页面间使用。
如果要实现从一个页面向到另一个页面传递消息,使用html5的API就可以实现。postMessage()就是用来试下跨文档消息传递的,不过这个API有局限,只能新开的页面传递消息(内嵌也可以)。
浏览器支持
Internet Explorer 8 以上版本支持 |
postMessage()
otherWindow.postMessage(message, targetOrigin, [transfer]);- otherWindow是目标窗口的引用,在当前场景下就是iframe.contentWindow;
- message是发送的消息,在Gecko 6.0之前,消息必须是字符串,而之后的版本可以做到直接发送对象而无需自己进行序列化。
- targetOrigin表示设定目标窗口的origin,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。对于保密性的数据,设置目标窗口origin非常重要。
- transfer可选参数,是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
当postMessage()被调用的时,一个消息事件就会被分发到目标窗口上。该接口有一个message事件,该事件有几个重要的属性:
otherwindow为要发送窗口 对象的引用,可以通过window.open()方法返回该对象,或通过对window.frames数组指定序号(index)或名字的方式来返回单个 frame所属性的窗口对象。
那么,当iframe初始化后,可以通过下面代码获取到iframe的引用并发送消息:
// 注意这里不是要获取iframe的dom引用,而是iframe window的引用 const iframe = document.getElementById('myIFrame').contentWindow; iframe.postMessage('hello world', 'https://www.qq344225443/cn');
在iframe中,通过下面代码即可接收到消息。
window.addEventListener('message', msgHandler, false);
在接收时,可以根据需要,对消息来源origin做一下过滤,避免接收到非法域名的消息导致的xss攻击。
实例
跨文档消息传输示例主文档 $(function() { // 监听message事件。 window.addEventListener("message", function(event) { // 忽略指定URL之外的页面发送的消息。 if(event.origin != "https://www.qq344225443/cn") return; alert(event.data); // 显示消息。 }, false); $("#iframeContent").load(function(event) { // 向子页面发送消息 this[0].postMessage("Hello", "https://www.qq344225443/cn/test/"); }); });跨域通信示例
子页面中的代码
$(function() { window.addEventListener("message", function(event) { if(event.origin != "https://www.baikegou.com") return; $("#console").append(event.origin).append("传来的消息:").append(event.data); // 向主页面发送消息。 event.source.postMessage("Hello, there is :" + this.location, event.origin); }, false); });这是iframe中的内容。
- 通过对window对象的message事件进行监听,可以接收消息。
- 通过访问message事件的origin属性,可以获取消息的发送源。注意:发送源与网站的URL地址不是一个概念,发送源只包括域名与 端口号,为了不接收其他源恶意发送过来的消息,最好对发送源做检查。
- 通过访问message事件的data属性,可以取得消息内容(可以是任何JavaScript对象,使用JSON)。
- 使用postMessage()方法发送消息。
- 通过访问message事件的source属性,可以获取消息发送源的窗口的代理对象。
一个页面内嵌另一个页面
// index.jsp页面(源页面) // 跨域发送数据到目标源 window.onload = function () { document.getElementsByTagName("iframe")[0].contentWindow.postMessage({name: 'wujiang'}, "http://localhost:8090"); } // 监听目标源发送过来的数据 window.addEventListener('message', function (e) { console.log('http://localhost:8090/a.ftl ===> http://localhost:8080/index.jsp'); console.log(e); })
// a.ftl页面(目标页面) // 监听其他窗口是否发送数据 if (window.addEventListener) { window.addEventListener('message', function (e) { if (e.origin !== 'http://localhost:8080') { return } console.log('http://localhost:8080/index.jsp ===> http://localhost:8090/a.ftl') // 打印数据 console.log(e) // 回传数据 e.source.postMessage('hello wujiang', e.origin) }, false) } else if (window.attachEvent) { window.attachEvent('onmessage', function (e) { if (e.origin !== 'http://localhost:8080') { return } console.log('http://localhost:8080/index.jsp ===> http://localhost:8090/a.ftl') // 打印数据 console.log(e) // 回传数据 e.source.postMessage('hello wujiang', e.origin) }, false) }
- data:发送的数据
- origin:源IP地址
- source:源窗口,可以通过source返回数据到源窗口
一个页面打开另一个页面
// 打开一个新窗口 var newWin = window.open('http://localhost:8090/a'); // 向新窗口发送数据 setTimeout(function () { console.log('http://localhost:8080/a.jsp ===> http://localhost:8090/a.ftl'); newWin.postMessage({name: 'wujiang'}, 'http://localhost:8090'); }, 1000);
鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com
图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!