關(guān)于iframe跨域使用postMessage的實(shí)現(xiàn)

當(dāng)我們要在域名A.com下使用一個(gè)域名B.com提供的頁面服務(wù),直覺想到的實(shí)現(xiàn)方式就是使用iframe。但是iframe直接的交互存在**跨域問題**,目前看來解決方式有兩種。一是使用nginx代理轉(zhuǎn)發(fā),在域名A的nginx上配置指定的轉(zhuǎn)發(fā)規(guī)則,直接指向域名B,直接干掉了跨域;另一種方式是使用postMessage方法。此處針對第二種方式,看下使用方式和可能的問題。
postMessage是什么
此處引用MDN關(guān)于postMessage的詳細(xì)說明。簡而言之就是:postMessage是掛載在window下的一個(gè)方法,用于不同域名下的兩個(gè)頁面的信息交互,父子頁面通過postMessage()發(fā)送消息,再通過監(jiān)聽message事件接收信息。
postMessage使用
假設(shè)有一個(gè)父頁面indexPage.html, 子頁面iframePage.html
一、父頁面向子頁面發(fā)送消息
// 父頁面index.html //獲取iframe元素 iFrame = document.getElementById('iframe') //iframe加載完畢后再發(fā)送消息,否則子頁面接收不到message iFrame.onload = function(){ //iframe加載完立即發(fā)送一條消息 iFrame.contentWindow.postMessage({msg: 'MessageFromIndexPage'},'\*'); }
iFrame.contentWindow.postMessage('MessageFromIndexPage','b.com')
方法的第一個(gè)參數(shù)是發(fā)送的消息,無格式要求;第二個(gè)參數(shù)是域名限制,當(dāng)不限制域名時(shí)填寫* ,第三個(gè)可選參數(shù)transfer一般不填,這個(gè)參數(shù)有嚴(yán)重的瀏覽器兼容問題。
二、子頁面接收父頁面發(fā)送的消息
// 子頁面iframePage.html //監(jiān)聽message事件 window.addEventListener("message", function(event){ console.log( '這里是接收到來自父頁面的消息,消息內(nèi)容在event.data屬性中', event ) }, false)
三、子頁面給父頁面?zhèn)鬟f消息
window.parent.postMessage({name: '張三'}, '\*');
方法的第一個(gè)參數(shù)是發(fā)送的消息,目前可無格式要求, 在 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)之前, 參數(shù) message 必須是一個(gè)字符串;第二個(gè)參數(shù)是域名限制,當(dāng)不限制域名時(shí)填寫’*‘
四、父頁面接收子頁面的消息
//監(jiān)聽message事件 window.addEventListener("message", function receiveMessageFromIframePage (event) { console.log('這里是子頁面發(fā)送來的消息,消息內(nèi)容在event.data屬性中', event) }, false);
postMessage的安全問題
使用postMessage交互,默認(rèn)就是允許跨域行為,一旦允許跨域,就會(huì)有一些安全問題,針對postMessage主要有兩種攻擊方式。一是偽造數(shù)據(jù)發(fā)送方(父頁面),易造成數(shù)據(jù)接收方(子頁面)受到XSS攻擊或其他安全問題;二是偽造數(shù)據(jù)接收方,類似jsonp劫持。
一、偽造數(shù)據(jù)發(fā)送方
攻擊方式:偽造一個(gè)父頁面,引導(dǎo)使用者觸發(fā)功能,發(fā)送消息給子頁面,如果子頁面將父頁面發(fā)送的消息直接插入當(dāng)前文檔流,就是引發(fā)XSS攻擊,或者子頁面使用父頁面?zhèn)鬟f的消息進(jìn)行其他操作,例如寫入數(shù)據(jù),造成安全問題。
防范方式:子頁面iframe對接收到的message信息做域名限制
// 子頁面iframePage.html //監(jiān)聽message事件 window.addEventListener("message", function(event){ origin = event.origin || event.originalEvent.origin if(origin == 'https://A.com'){ console.log( '這里是接收到來自父頁面的消息,消息內(nèi)容在event.data屬性中', event ) } }, false)
二、偽造數(shù)據(jù)接收方
攻擊方式:偽造一個(gè)子頁面,在父頁面中引入子頁面,在偽造的頁面中接收父頁面發(fā)送的消息,此時(shí)可以獲取用戶的敏感消息。
防范方式:父頁面對發(fā)送消息的頁面做域名限制
// 父頁面index.html //獲取iframe元素 iFrame = document.getElementById('iframe') //iframe加載完畢后再發(fā)送消息,否則子頁面接收不到message iFrame.onload = function(){ //iframe加載完立即發(fā)送一條消息 iFrame.contentWindow.postMessage('MessageFromIndexPage','https://B.com'); }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
HTML5 window/iframe跨域傳遞消息 API介紹
window.postMessage允許多個(gè) window/frame之間跨域傳遞數(shù)據(jù)和信息。下面為大家介紹下window.postMessage的工作原理,以及如何在FireFox,IE8+,Opera,Safari和Chrome中使用2013-08-26Iframe 高度自適應(yīng)(兼容IE/Firefox、同域/跨域)
在實(shí)際的項(xiàng)目進(jìn)行中,很多地方可能由于歷史原因不得不去使用iframe,包括目前正火熱的應(yīng)用開發(fā)也是如此。2010-03-17