詳解iframe跨域的幾種常用方法(小結(jié))
背景
隨著業(yè)務(wù)的發(fā)展,自然地會(huì)有一些公共的業(yè)務(wù)被抽離成為公共組件共各個(gè)項(xiàng)目使用。但是由于各個(gè)項(xiàng)目用到的技術(shù)棧都有所不同,所以這個(gè)公共組件就不能方便地被引用了。為解決這個(gè)問(wèn)題,我們把這個(gè)組件寫(xiě)成了單獨(dú)的頁(yè)面掛到一個(gè)域名下,其他項(xiàng)目采用iframe或者webview的方式去加載這個(gè)頁(yè)面,從而實(shí)現(xiàn)功能的簡(jiǎn)單復(fù)用。
不過(guò)這過(guò)程中也產(chǎn)生了很多問(wèn)題,單是跨域就會(huì)出現(xiàn)好幾次了。以下我將會(huì)介紹我遇到的跨域問(wèn)題以及一些解決方法。
為什么會(huì)跨域
為了保證用戶(hù)信息的安全,95年的時(shí)候Netscape公司引進(jìn)了同源策略,里面的同源指的是三個(gè)相同:協(xié)議、域名、端口。
違反了同源策略就會(huì)出現(xiàn)跨域問(wèn)題,主要表現(xiàn)為以下三方面:
- 無(wú)法讀取cookie、localStorage、indexDB
- DOM無(wú)法獲得
- ajax請(qǐng)求無(wú)法發(fā)送
場(chǎng)景
最近在做一個(gè)需求,需要用iframe引入一個(gè)別人封裝好的類(lèi)似視頻播放器的東西。iframe里面有一個(gè)全屏的按鈕,點(diǎn)擊后需要頁(yè)面讓iframe全屏,由于受到同源策略的限制,iframe無(wú)法告訴頁(yè)面全屏。
解決辦法
設(shè)置domain
document.domain作用是獲取/設(shè)置當(dāng)前文檔的原始域部分,同源策略會(huì)判斷兩個(gè)文檔的原始域是否相同來(lái)判斷是否跨域。這意味著只要把這個(gè)值設(shè)置成一樣就可以解決跨域問(wèn)題了。
在此我將domain設(shè)置為一級(jí)域名的值,a頁(yè)面url為a.demo.com,a頁(yè)面中iframe引用的b頁(yè)面url為b.demo.com,具體設(shè)置為
document.domain = 'demo.com'
設(shè)置完之后,在a頁(yè)面的window上掛載使iframe全屏的方法
// a頁(yè)面 window.toggleFullScreen = () => { // do something }
在b頁(yè)面上可以直接獲取到a頁(yè)面的window對(duì)象并直接調(diào)用
// b頁(yè)面 window.parent.toggleFullScreen()
但是這個(gè)值的設(shè)置也有一定限制,只能設(shè)置為當(dāng)前文檔的上一級(jí)域或者是跟該文檔的URL的domain一致的值。如url為a.demo.com,那domain就只能設(shè)置為demo.com或者a.demo.com。因此,設(shè)置domain的方法只能用于解決主域相同而子域不同的情況。
使用中間頁(yè)面
我們還可以使用一個(gè)與a頁(yè)面同域名但不同路由的c頁(yè)面作為中間頁(yè)面,b頁(yè)面加載c頁(yè)面,c頁(yè)面調(diào)用a頁(yè)面的方法,從而實(shí)現(xiàn)b頁(yè)面調(diào)用a頁(yè)面的方法。具體操作如下:
在a頁(yè)面的node層新開(kāi)一個(gè)路由,此路由加載一個(gè)c頁(yè)面作為中間頁(yè)面,c頁(yè)面的url為a.demo.com/c。c頁(yè)面只是一個(gè)簡(jiǎn)單的html頁(yè)面,在window的onload事件上調(diào)用了a頁(yè)面的方法。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script> window.onload = function () { parent.parent.toggleFullScreen(); } </script> </body> </html>
由于c頁(yè)面和a頁(yè)面是符合同源策略的,所以可以避開(kāi)跨域問(wèn)題,執(zhí)行全屏的方法。
postmessage
window.postMessage方法可以安全地實(shí)現(xiàn)跨源通信,寫(xiě)明目標(biāo)窗口的協(xié)議、主機(jī)地址或端口就可以發(fā)信息給它。
// b頁(yè)面 parent.postMessage( value, "http://a.demo.com" );
// a頁(yè)面 window.addEventListener("message", function( event ) { if (event.origin !== 'http://b.demo.com') return; toggleFullScreen() });
為了安全,收到信息后要檢測(cè)下event.origin判斷是否要收信息的窗口發(fā)過(guò)來(lái)的。
總結(jié)
通過(guò)以上的方法,我們就可以和iframe自由通信啦。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javascript里模擬sleep(兩種實(shí)現(xiàn)方式)
有幾種方式,但都不完美 其一:不斷循環(huán),直到達(dá)到指定時(shí)間、其二:用xhr同步請(qǐng)求后臺(tái)程序,比如傳2000過(guò)去,后臺(tái)就sleep 2秒后再返回,這種方式也有缺點(diǎn),當(dāng)N多客戶(hù)端都請(qǐng)求后臺(tái)時(shí),一直保持連接http開(kāi)銷(xiāo)很大,感興趣的朋友可以了解下啊2013-01-01原生JavaScript實(shí)現(xiàn)精美的淘寶輪播圖效果示例【附demo源碼下載】
這篇文章主要介紹了原生JavaScript實(shí)現(xiàn)精美的淘寶輪播圖效果,結(jié)合完整實(shí)例形式詳細(xì)分析了javascript實(shí)現(xiàn)淘寶輪播圖功能的相關(guān)HTML布局、css及js核心功能代碼,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2017-05-05js中style.display=""無(wú)效的解決方法
這篇文章主要介紹了js中style.display=""無(wú)效的解決方法,是js程序設(shè)計(jì)中非常常見(jiàn)的問(wèn)題,需要的朋友可以參考下2014-10-10JS中動(dòng)態(tài)創(chuàng)建元素的三種方法總結(jié)(推薦)
下面小編就為大家?guī)?lái)一篇JS中動(dòng)態(tài)創(chuàng)建元素的三種方法總結(jié)(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10使用JavaScript字符串解決回文數(shù)的方案詳解
這篇文章主要介紹了使用JavaScript字符串解決回文數(shù)的方案,JavaScript中的字符串是一種數(shù)據(jù)類(lèi)型,用于表示文本數(shù)據(jù),字符串可以包含任意字符序列,包括字母、數(shù)字、符號(hào)和空格,靈活掌握字符串的解決問(wèn)題思想,巧用字符串解決回文數(shù),需要的朋友可以參考下2024-05-05js根據(jù)手機(jī)客戶(hù)端瀏覽器類(lèi)型,判斷跳轉(zhuǎn)官網(wǎng)/手機(jī)網(wǎng)站多個(gè)實(shí)例代碼
這篇文章主要介紹了js根據(jù)手機(jī)客戶(hù)端瀏覽器類(lèi)型,判斷跳轉(zhuǎn)官網(wǎng)/手機(jī)網(wǎng)站多個(gè)實(shí)例代碼,需要的朋友可以參考下2016-04-04JavaScript 全面解析各種瀏覽器網(wǎng)頁(yè)中的JS 執(zhí)行順序
近來(lái)我通過(guò)一些測(cè)試以全面的解析網(wǎng)頁(yè)在各種瀏覽器中的JavaScript代碼的執(zhí)行順序,在這兒做個(gè)記錄。2009-02-02JavaScript實(shí)現(xiàn)簡(jiǎn)單的拖拽效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單的拖拽效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11JavaScript中值類(lèi)型和引用類(lèi)型的區(qū)別
本文主要介紹了JavaScript中值類(lèi)型和引用類(lèi)型的區(qū)別,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02