跨域的N种方法之postMessage

一、技术背景

  postMessage是html5引入的API可以更方便、有效、安全的解决这些问题。postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

二、使用

  otherWindow.postMessage(message, targetOrigin, [transfer])方法接受两个参数

    otherWindow:其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames

    data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
    origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

三、具体实践

  1、A域中的index页面

    ①动态(或者直接在文档内)创建一个iframe标签。src指向数据源(B域index)页面。

    ②ifr加载完成通过ifr.contentWindow属性获取B域中的window对象。然后通过该window对象下的postMessage方法发送数据

    ③第一个参数为要传送的数据,最好为字符串。第二个参数为要发送数据的目标,即数据源。

    ④通过监听window对象的message事件,通过回调函数接收数据源返回的数据。

<!DOCTYPE html>
<html>
<head>
    <title>A域=>postMessage跨域实践</title>
</head>
<body>
    <input id="data" type="text" name="" value="">
    <button id="post">点击发送</button>
</body>
<script type="text/javascript">
    var ifr = document.createElement("iframe")
        ifr.style.display="none";
        ifr.src="http://top.jiangqi.cn:8081/index3.html"
    post.onclick=function(){
        var data = document.getElementById("data").value;
        document.getElementsByTagName("head")[0].appendChild(ifr);
        ifr.onload = function(){
            ifr.contentWindow.postMessage(JSON.stringify(data),"http://top.jiangqi.cn:8081/index3.html")
        }
    }
    window.addEventListener("message",function(e){
     console.log(e) console.log(e.data) },
false) </script> </html>

  2、B域中的index页面:

    ①通过监听window的message消息,回调接收A域传过来的参数。

    ②window.parent获取父窗口的引用。然后通过postMessage返回数据给A域

<!DOCTYPE html>
<html>
<head>
    <title>B域=>postMessage跨域实践</title>
</head>
<body>

</body>
<script type="text/javascript">
    window.addEventListener("message",function(e){
        if(JSON.parse(e.data)){
            window.parent.postMessage("我已经收到data:"+e.data,"http://www.jiangqi.cn/index3.html")
        }
    },false)
</script>
</html>

四、使用注意事项

  1、用于接收消息的任何事件监听器必须首先使用origin和source属性来检查消息的发送者的身份。 这不能低估:无法检查origin和source属性会导致跨站点脚本攻击。

  2、其他安全问题(见参考)

五、参考

  1、https://www.secpulse.com/archives/56637.html

  2、https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

posted @ 2019-04-03 10:54  Hello_nico  阅读(2810)  评论(0编辑  收藏  举报