一、背景
1.为了保证用户信息的安全,Netscape公司在1995年引进了同源策略:不同源的页面不能相互通信。里面的同源指的是三个相同:协议、域名、端口。
违反了同源策略就会出现跨域问题,主要表现为以下三方面:
- 无法读取cookie、localStorage、indexDB
- 无法获得DOM
- 无法发送ajax请求
2.实际业务场景中会有子服务和父服务布在相同站点的不同端口上,为了实现业务集成,需要使用iframe,且必须打通子iframe和父iframe之间双向通信的通道
二、如何实现iframe跨域通信?
1.设置domain
2.使用代理页面
3.postMessage方法:window对象上的一个用来解决跨域通信问题的方法
三、方案描述
选用postMessage方法
【1】message: 要发送到其他 window的数据,可以是任何原始类型的数据,它将会被结构化克隆算法序列化,这意味着你可以不受限制地将数据对象安全地传送给目标窗口而无需自己序列化
【2】targetOrigin :
- 指定哪些窗口能接收到消息事件,若当前子页面的url和设置的不一致,则发送失败。设置为*代表所有url都允许发送
- 如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
【3】transfer :是一串和message 同时传递的 Transferable
对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
//发送消息
otherWindow.postMessage(message, targetOrigin, [transfer]);
//监听message事件,接收消息
window.addEventListener('message',function(event){
//do something
},false)
具体应用
- 从父页面向子页面发消息
//创建iframe,获取iframe dom 元素
iframe = document.getElementById('iframeName')
//iframe加载完毕后,获取iframe的window对象并调用其postMessage方法,给子页面发消息
iframe.onload = function(){
iframe.contentWindow.postMessage('This is message from parent page','*')
}
- 子页面接收消息
//监听message事件
window.addEventListener("message", receiveMessageFromIframePage, false);
//回调函数
function receiveMessageFromIframePage (event) {
console.log('receiveMessageFromIframePage', event)
}
- 注意
window.addEventListener注册的message事件除了监听iframe发送的事件,还会监听其他应用发送的事件,所以在接收消息的回调函数中需要用好event对象,确定接收到的是自己想要的信息