当我们想在域名A.com下使用域名B.com提供的页面服务时,最直观的实现方式就是使用iframe。但是iframe直接交互存在**跨域问题**。目前看来有两种解决方案。一种是使用nginx代理转发,在域名A的nginx上配置指定的转发规则,直接指向域名B,直接kill跨域;另一种方法是使用postMessage方法。这里针对第二种方法,我们看看用法和可能出现的问题。什么是postMessage这里有一个关于postMessage的MDN的详细说明。简而言之:postMessage是挂载在window下的一个方法,用于不同域名下的两个页面之间的信息交互。父子页面通过postMessage()发送消息,然后通过监听消息事件接收信息。postMessage的使用假设有父页面indexPage.html和子页面iframePage.html1.父页面向子页面发送消息//父页面index.html//获取iframe元素iFrame=document.getElementById('iframe')//iframe加载后发送消息,否则子页面收不到消息iFrame.onload=function(){//iframe加载完成后立即发送消息iFrame.contentWindow.postMessage({msg:'MessageFromIndexPage'},'\*');}iFrame.contentWindow.postMessage('MessageFromIndexPage','b.com')该方法第一个参数为发送的消息,无格式要求;第二个参数为域名限制,不限制域名时填写*,第三个可选参数传输一般不填写,该参数存在严重的浏览器兼容性问题。2.子页面接收父页面发送的消息//子页面iframePage.html//监听消息事件window.addEventListener("message",function(event){console.log('这里是消息从父页面收到,消息内容在event.data属性中',event)},false)三、子页面向父页面发送消息window.parent.postMessage({name:'张三'},'\*');第一种方法第一个参数是要发送的消息,目前没有格式要求,在Gecko6.0(Firefox6.0/Thunderbird6.0/SeaMonkey2.3)之前,参数message必须是字符串;第二个参数为域名限制,不限制域名时填写'*'4.父页面接收子页面的消息//监听消息事件window.addEventListener("message",functionreceiveMessageFromIframePage(event){console.log('这里是子页面发送的消息,消息内容在event.data属性中',event)},false);postMessage的安全问题使用postMessage进行交互,默认是允许跨域行为。一旦允许跨域行为,就会出现一些安全问题。postMessage主要有两种攻击方式。一是伪造数据发送端(父页面),容易导致数据接收端(子页面)被XSS攻击或其他安全问题;另一种是伪造数据接收方,类似于jsonp劫持。1、伪造数据发送者攻击方式:伪造父页面,引导用户触发功能,向子页面发送消息。如果子页面直接将父页面发送的消息插入到当前文档流中,会触发XSS攻击,或者子页面使用父页面传递过来的消息进行其他操作,比如写数据,造成安全问题.防止方法:子页面iframe限制接收消息信息的域名//子页面iframePage.html//监听消息事件window.addEventListener("message",function(event){origin=event.origin||event.originalEvent.originif(origin=='https://A.com'){console.log('这里是从父页面收到的消息,消息内容在event.data属性中',event)}},false)二、伪造数据接收者攻击方式:伪造子页面,将子页面引入父页面,在伪造的页面中接收父页面发送的消息,此时用户的敏感信息可以获得。防止方法:父页面限制发送消息页面的域名//父页面index.html//获取iframe元素iFrame=document.getElementById('iframe')//加载iframe后发送消息,否则子页面无法接收到消息iFrame.onload=function(){//iframe加载完成后立即发送消息iFrame.contentWindow.postMessage('MessageFromIndexPage','https://B.com');}参考:https://juejin.im/post/590c39...https://p0sec.net/index.php/a...
