postMessage處理iframe 跨域問題

背景:因爲同源策略存在,javascript的跨域一直都是一個棘手的問題。父頁面沒法直接獲取iframe內部的跨域資源;同時,iframe內部的跨域資源也沒法將信息直接傳遞給父頁面javascript

一:傳統的解決方式。

傳統的iframe資源解決方式:主要經過經過中間頁面代理,此處再也不贅述,參考中間頁獲取跨域iframehtml

二:html5 postMessage的產生

隨着HTML5的發展,html5工做組提供了兩個重要的接口:postMessage(send) 和 onmessage。這兩個接口有點相似於websocket,能夠實現兩個跨域站點頁面之間的數據傳遞。html5

postMessage APIjava

下面是實踐過程當中兩個小栗子:分別父頁面傳遞信息給iframe,iframe傳遞信息給父頁面。web

三:iframe獲取父頁面信息

話很少說,直接上碼:
參考demo:父頁面傳給子頁面demo跨域

父頁面代碼

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>崔渙 iframe postmessage 父頁面</title>
    <script type="text/JavaScript">
        function sendIt() {
            // 經過 postMessage 向子窗口發送數據
            document.getElementById("otherPage").contentWindow
                    .postMessage(
                    document.getElementById("message").value,
                    "http://cuihuan.net:8003"
            );
        }
    </script>
</head>
<body>
<!-- 經過 iframe 嵌入子頁面 -->
<iframe src="http://cuihuan.net:8003/test.html" id="otherPage"></iframe>
<br/>
<br/>
<input type="text" id="message"/>
<input type="button" value="Send to child.com" onclick="sendIt()"/>
</body>
</html>

子頁面代碼

<html> 
 <head> 
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
 <title>崔渙測試子頁面信息</title> 
 <script type="text/JavaScript"> 
     //event 參數中有 data 屬性,就是父窗口發送過來的數據
     window.addEventListener("message", function( event ) { 
         // 把父窗口發送過來的數據顯示在子窗口中
       document.getElementById("content").innerHTML+=event.data+"<br/>"; 
     }, false ); 

 </script> 
 </head> 
 <body> 
     this is the 8003 port for cuixiaozhuai 
     <div id="content"></div> 
 </body> 
 </html>

demo 效果以下圖:兩個跨域頁面之間,父頁面給子頁面傳遞數據。
16743333-E2AF-40E5-8DD2-0CBCE8919C66安全

四:iframe傳遞信息給父頁面

參考demo:跨域子頁面傳給父頁面demowebsocket

父頁面代碼

<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>崔渙測試父頁面</title>
 <script type="text/JavaScript">
     //event 參數中有 data 屬性,就是父窗口發送過來的數據
     window.addEventListener("message", function( event ) {
         // 把父窗口發送過來的數據顯示在子窗口中
       document.getElementById("content").innerHTML+=event.data+"<br/>";
     }, false );

 </script>
 </head>
 <body>
     <iframe src="http://cuihuan.net:8003/iframeSon.html" id="otherPage"></iframe>
     <br/>
     this is the 1015 port for cuixiaozhuai。
     <div id="content"></div>
 </body>
 </html>

子頁面代碼

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>崔小渙iframe postmessage 測試頁面</title>
    <script type="text/JavaScript">
        function sendIt() {
            // 子頁面給父頁面傳輸信息 
            parent.postMessage(
                document.getElementById("message").value,
                "http://cuihuan.net:1015"
            );
        }
    </script>
</head>
<body>
<br/>
this is the  port for cuixiaozhuai
<input type="text" id="message"/>
<input type="button" value="Send to child.com" onclick="sendIt()"/>
</body>
</html>

demo 效果以下圖:兩個跨域頁面之間,子頁面傳遞數據給父頁面傳遞數據。
22433B4C-8836-4546-93DB-7A896F8B4B37dom

五:postmessage簡單分析和安全問題

postmessage 傳送過來的信息以下圖,
BABB5101-CD9D-448C-99EE-910334405D3Dsocket

幾乎包含了全部應該有的信息。甚至data中能夠包含object,出於安全考慮能夠域的校驗,數據規則的校驗安全校驗,以下代碼

window.addEventListener('message', function (event) {
        
        //校驗函數是否合法
        var checkMessage = function () {
            // 只獲取須要的域,並不是全部均可以跨域
            if (event.origin != "need domain") {
                return false;
            }

            
            var message = event.data;
            // 傳輸數據類型校驗
            if (typeof(message) !== 'object') {
                return false;
            }

            // message 的rule中包含xxx則爲xxx須要字段。
            return message.rule === "xxx";
        };

        if (checkMessage()) {
            // 經過校驗進行相關操做
            addDetailFunc(event);
        }
    });

【轉載請註明:postMessage處理iframe 跨域問題 | 靠譜崔小拽

相關文章
相關標籤/搜索