深入淺出iframe

前言

說起iframe,大家都會(huì)覺得很嫌棄或者很不愿接近,原因大概都是:能耗高,安全問題,spider不喜歡它...也有(不少)同學(xué)內(nèi)心獨(dú)白就是:不!這很low很dirty,我才不想用惹!但是我們必須的承認(rèn)iframe之強(qiáng)大,很多時(shí)候我們都會(huì)(不得不)使用它,真的素又愛又恨吶-8-

今天就在這里和大家一起好好討論一下iframe。

iframe基本概念

我們先看一個(gè)??

<iframe src="demo.html" height="300" width="500" name="demo" scrolling="auto" sandbox="allow-same-origin"></iframe>

iframe的一些基本屬性:

  • src iframe頁面地址,有同域跨域之分
  • height iframe高度
  • width iframe寬度
  • name iframe命名,可通過window.frames[xxx]被調(diào)用
  • scrolling iframe滾動(dòng)模式
  • sandbox html5新特性,用于限制iframe的功能

使用iframe的正確姿勢

我們可以通過contentWindowcontentDocument兩個(gè)API獲取iframe的window對(duì)象和document對(duì)象。

let iframe = document.getElementById('demo');
let iwindow = iframe.contentWindow; // 獲取iframe的window對(duì)象
let idoc = iframe.contentDocument; // 獲取iframe的document對(duì)象

剛剛我們提到了iframe的name屬性,我們也可以通過window.frames[iframeName]來調(diào)用iframe。

let iframe = window.frames['demo']

iframe使用父級(jí)內(nèi)容的正確姿勢

我們通過window.self,window.parentwindow.top這三個(gè)屬性分別獲取自身window對(duì)象,父級(jí)window對(duì)象,頂級(jí)window對(duì)象。

看圖說話


iframe1.self === iframe1
iframe1.parent === iframe2
iframe2.parent === window
iframe1.top === window

同域/跨域

什么是同域什么跨域咧?同域跨域的區(qū)別在哪咧?我們一般會(huì)使用iframe來進(jìn)行父子頁面的通信,然鵝父子頁面是否同域決定了它們之間能否進(jìn)行通信。

js遵循同源策略,即同協(xié)議,同域名,同端口號(hào),否則都算跨域。

同源策略 是由Netscape提出的一個(gè)著名的安全策略,現(xiàn)在所有支持JavaScript 的瀏覽器都會(huì)使用這個(gè)策略。實(shí)際上,這種策略只是一個(gè)規(guī)范,并不是強(qiáng)制要求,各大廠商的瀏覽器只是針對(duì)同源策略的一種實(shí)現(xiàn)。它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會(huì)受到影響。

跨域 簡單的來說,指的是兩個(gè)資源非同源。出于安全方面的考慮,頁面中的JavaScript在請(qǐng)求非同源的資源時(shí)就會(huì)出 跨域問題 ——即跨域請(qǐng)求,這時(shí),由于同源策略,我們的請(qǐng)求會(huì)被瀏覽器禁止。也就出現(xiàn)了 我們常說的 跨域 問題。

通過這個(gè)圖可以進(jìn)一步幫助我們理解同域和跨域。

iframe跨域通訊之document.domain

對(duì)于主域相同子域不同的兩個(gè)頁面,我們可以通過document.domain + iframe來解決跨域通信問題。

舉個(gè)??,網(wǎng)頁a(http://www.easonwong.com)和網(wǎng)頁b(http://script.easonwong.com),兩者都設(shè)置document.domain = 'easonwong.com'(這樣瀏覽器就會(huì)認(rèn)為它們處于同一個(gè)域下),然后網(wǎng)頁a再創(chuàng)建iframe上網(wǎng)頁b,就可以進(jìn)行通信啦~!

網(wǎng)頁a

document.domain = 'easonwong.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.easonwong.com';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
    let doc = ifr.contentDocument || ifr.contentWindow.document;
    // 在這里操縱b.html
};

網(wǎng)頁b

document.domain = 'easonwong.com';

iframe跨域通訊之postMessage

postMessage是html5的新特性,具體介紹不在此贅述。

postMessage介紹

MDN postMessage

兼容性 IE8以上

can I use

我們可以通過html5這個(gè)新特性進(jìn)行iframe間的跨域通信,使用postMessage進(jìn)行數(shù)據(jù)傳遞,通過Message監(jiān)聽通信事件。舉個(gè)??

網(wǎng)頁a

document.domain = 'easonwong.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.easonwong.com';
ifr.style.display = 'none';
document.body.appendChild(ifr);
// 發(fā)送數(shù)據(jù)
ifr.postmessage('hello, I`m a', 'http://script.easonwong.com');

網(wǎng)頁b

// 監(jiān)聽message事件
window.addEventListener('message', receiver, false);
function receiver(e) {
    if (e.origin == 'http://www.easonwong.com') {
        if (e.data == 'hello, I`m a') {
            e.source.postMessage('hello, I`m b', e.origin);信息
        }
    }
}

iframe實(shí)現(xiàn)JSBridge

在移動(dòng)端Hybrid混合模式中經(jīng)常用到JSBridge進(jìn)行JS和Native之間的通信,其中我們可以通過iframe的方式實(shí)現(xiàn)JS調(diào)用Native的方法。

以上提到的方法就是URL SCHEME攔截。

URL SCHEME是一種類似于url的鏈接,是為了方便app直接互相調(diào)用設(shè)計(jì)的,形式和普通的 url 近似,主要區(qū)別是 protocol 和 host 一般是自定義的,例如: easonwong://hh/url?name=easonwong,其中protocol是easonwong,host則是hh。

我們通過創(chuàng)建一個(gè)iframe(src設(shè)為我們自定義的URL SCHEME)來發(fā)送請(qǐng)求,然后Native那邊可以攔截到請(qǐng)求并獲取其中帶有的參數(shù),即可進(jìn)行后續(xù)的操作。

想了解更多具體的關(guān)于JSBridge的內(nèi)容,可以閱讀我的JSBridge學(xué)習(xí)筆記

iframe的其他用途

  • 用iframe進(jìn)行異步請(qǐng)求

在很久很久很久以前,久到ajax還沒出現(xiàn)的時(shí)候,人們會(huì)用iframe來進(jìn)行異步請(qǐng)求。大概就是異步創(chuàng)建iframe,然后后臺(tái)返回?cái)?shù)據(jù)在iframe中,我們在從里面獲取數(shù)據(jù)。

例如在我做過的一個(gè)項(xiàng)目中,通過iframe.src傳入一個(gè)文件下載地址,實(shí)現(xiàn)無需打開新窗口下載文件。

  • 引用/展示第三方內(nèi)容

  • 需要獨(dú)立樣式和帶有交互的內(nèi)容,例如幻燈片

  • sandbox沙箱隔離

  • 歷史記錄管理

iframe的安全問題

iframe小廣告

很讓我們討厭iframe的一點(diǎn),就是很多*網(wǎng)站都會(huì)有各種讓人防不勝防的小廣告,它們大多就是用通過iframe實(shí)現(xiàn)的,本來想點(diǎn)擊某個(gè)播放按鈕,結(jié)果馬鴨直接跳幾十跳不知道去了哪個(gè)新世界去了。

更討厭的一種情況是,可能不知道哪天用戶突然拿刀過來,說我們的項(xiàng)目頁面里出現(xiàn)了野雞廣告,說我們在消費(fèi)他們,一臉懵逼的我們覺得十分無辜。實(shí)際上就是我們的頁面被運(yùn)行商劫持了,被掛上了注入了不知名的野雞廣告。

所以我們一定要注意在用iframe的同時(shí),要防止我們被iframe了。

防嵌套頁面操作

在前端領(lǐng)域,我們可以通過window.top來防止我們頁面被嵌套。

if(window != window.top){
    window.top.location.href = myURL;
}

或者通過window.location.host來檢測是否跨域了

if (top.location.host != window.location.host) {
  top.location.href = window.location.href;
}

而后端也可以做對(duì)應(yīng)的防范措施,通過設(shè)置X-Frame-Options響應(yīng)頭來確保自己網(wǎng)站的內(nèi)容沒有被嵌到別人的網(wǎng)站中去,也從而避免了點(diǎn)擊劫持 (clickjacking) 的攻擊。

CSP

內(nèi)容安全策略(CSP)用于檢測和減輕用于 Web 站點(diǎn)的特定類型的攻擊,例如 XSS 和數(shù)據(jù)注入等。

MDN CSP

通過CSP配置sandbox和child-src可以設(shè)置iframe的有效地址,它限制適iframe的行為,包括阻止彈出窗口,防止插件和腳本的執(zhí)行,而且可以執(zhí)行一個(gè)同源策略。

用法

  • 我們可以在html頭部中加上<meta>標(biāo)簽
    <meta http-equiv="Content-Security-Policy" content="child-src 'unsafe-inline' 'unsafe-eval' www.easonwong.com">
  • 或者通過HTTP頭部信息加上Content-Security-Policy字段

想了解更多具體的關(guān)于CSP或者XSS攻擊等網(wǎng)絡(luò)安全內(nèi)容,可以閱讀我的網(wǎng)絡(luò)攻擊與安全防御學(xué)習(xí)筆記

參考文章

iframe,我們來談一談

Iframe 有什么好處,有什么壞處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,250評(píng)論 6 530
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 97,923評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,041評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,475評(píng)論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,253評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,801評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,882評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,023評(píng)論 0 285
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,530評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,494評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,639評(píng)論 1 366
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,177評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,890評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,289評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,552評(píng)論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,242評(píng)論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,626評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容

  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實(shí)際上跨域的范圍絕對(duì)不止那么狹隘。具體概念如下:只要協(xié)議...
    w_zhuan閱讀 520評(píng)論 0 0
  • 什么是跨域? 2.) 資源嵌入:、、、等dom標(biāo)簽,還有樣式中background:url()、@font-fac...
    電影里的夢i閱讀 2,380評(píng)論 0 5
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實(shí)際上跨域的范圍絕對(duì)不止那么狹隘。具體概念如下:只要協(xié)議...
    他在發(fā)呆閱讀 826評(píng)論 0 0
  • 什么是跨域 跨域,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對(duì)JavaScript實(shí)...
    Yaoxue9閱讀 1,309評(píng)論 0 6
  • 《小王子》里沒有生僻的字,沒有晦澀的情節(jié),簡簡單單、真真切切的童真就足夠感人肺腑?!缎⊥踝印芬还?7章,宗宗從今天...
    Zack要多喝熱水閱讀 4,613評(píng)論 4 7