iframe特性全解讀

前言

在平時的開發中,或多或少會用到iframe,大部分時候咱們只須要簡單的使用iframe標籤,設置個寬高便可,不多回去深究iframe的別的特性。好比這種用法:html

<iframe src='https://blog.5udou.cn'>
複製代碼

但直到產品經理要求說,iframe嵌入的頁面可不可讓主頁面的url地址發生變化呀?好吧,一會兒懵圈了,我得去查查資料,因而索性就深究深究iframe的一些特性,省得再次尷尬。git

下面全部代碼均可以在這裏找到:github.com/linxiaowu66…github

iframe的特性

iframe的特性都是依賴參數配置實現的,現整理以下有用的屬性:web

屬性 解釋 備註
allow 能夠爲iframe指定特性策略
allowfullscreen 是否容許iframe調用requestFullscreen()方法激活全屏模式,這個屬性等同於allow屬性的這個配置:allow="fullscreen"
allowpaymentrequest 是否容許一個跨域的iframe調用支付請求API
csp 內嵌的資源強制實行同源策略
height iframe的高度,默認150px
importance 標識在iframe屬性src指示的資源的下載優先級,有auto/high/low三個等級
name 內嵌的瀏覽內容的目標名稱
referrerpolicy 指示當獲取frame的資源的時候攜帶的referrer,默認是no-referrer-when-downgrade,也就是僅當發生協議降級(如 HTTPS 頁面引入 HTTP 資源,從 HTTPS 頁面跳到 HTTP 等)時不發送 Referrer 信息。這個規則是如今大部分瀏覽器默認所採用的;
sandbox 在frame上的內容上運用額外的一下限制,具體哪些字段咱們下面詳細解釋

iframe的allow屬性詳解

allow屬性的使用須要參考特性策略這一小節。特性策略能夠容許你控制頁面或者iframe可使用哪些特性。頁面控制的話設置在HTTP頭部的Feature-Policy的這個字段,iframe的話就是咱們要說的這個allow字段。跨域

特性策略的書寫規則是:<feature name> <allowlist of origin(s)>數組

完整的特性名稱參考: Policy Controlled Features或者Feature-Policy 瀏覽器

而allowlist則有以下規則:安全

  1. *:表示該特性在該文檔下都是容許的,包括全部的嵌套的瀏覽內容(iframes),而不用管這些內容的源。
  2. self:表示該特性在該文檔下都是容許的,而且僅在同源的狀況下嵌套的瀏覽內容(iframes)纔可使用。
  3. src:(iframes的allow屬性專用)表示該特性在這個iframe下容許使用,只要加載的文檔來源的源和iframe的src屬性指定的URL是同源的。
  4. none:表示該特性在頂層以及嵌套的瀏覽內容下都是被禁用的
  5. <origin(s)>:表示該特性只在一些指定的源下才容許使用,多個源使用空格隔開

今天咱們主要講一下iframe下的allow屬性,好比你不容許iframe的頁面全屏、不容許調用攝像頭之類的行爲,能夠這麼配置:bash

<iframe allow="camera 'none'; fullscreen 'none'">app

好比只容許同源的纔可使用全屏這個特性:

<iframe src="https://example.com..." allow="fullscreen 'src'"></iframe>

好比只容許指定源纔可使用定位功能:

<iframe src="https://google-developers.appspot.com/demos/..." allow="geolocation https://google-developers.appspot.com"></iframe>

iframe的referrerpolicy屬性詳解

這個屬性牽扯到了HTTP的referer策略,咱們知道referer的策略是這樣的:

  • No Referrer:任何狀況下都不發送 Referrer 信息;
  • No Referrer When Downgrade:僅當發生協議降級(如 HTTPS 頁面引入 HTTP 資源,從 HTTPS 頁面跳到 HTTP 等)時不發送 Referrer 信息。這個規則是如今大部分瀏覽器默認所採用的;
  • Origin Only:發送只包含 host 部分的 Referrer。啓用這個規則,不管是否發生協議降級,不管是本站連接仍是站外連接,都會發送 Referrer 信息,可是隻包含協議 + host 部分(不包含具體的路徑及參數等信息);
  • Origin When Cross-origin:僅在發生跨域訪問時發送只包含 host 的 Referrer,同域下仍是完整的。它與 Origin Only 的區別是多判斷了是否 Cross-origin。須要注意的是協議、域名和端口都一致,纔會被瀏覽器認爲是同域;
  • Unsafe URL:不管是否發生協議降級,不管是本站連接仍是站外連接,通通都發送 Referrer 信息。正如其名,這是最寬鬆而最不安全的策略;

好比咱們這樣配置:

<iframe allow="fullscreen 'none'" referrerpolicy="no-referrer" src='http://127.0.0.1:3000/iframe.html'></iframe>
複製代碼

咱們經過抓包能夠看到對應的請求是這樣的:

iframe的sandbox屬性詳解

iframe的沙箱模式能夠提供一些額外的配置,當你把一個iframe置爲沙箱的時候,意味着沙箱內的內容的行爲全憑你控制了。

好比你在iframe下這樣配置:

<iframe sandbox="" src='http://127.0.0.1:3000/iframe1.html'></iframe>

可是iframe1.html中卻有對應的js腳本,那麼在控制檯下能夠看到這樣的報錯:

Blocked script execution in 'http://127.0.0.1:3000/iframe1.html' because the document's frame is sandboxed and the 'allow-scripts' permission is not set. 複製代碼

因此當你的iframe有腳本的時候,基本上都會配置allow-scripts這個屬性。

再好比你的頁面會有form標籤提交數據的時候,若是沒有allow-forms,則會報這種錯誤:

Blocked form submission to '' because the form's frame is sandboxed and the 'allow-forms' permission is not set. 複製代碼

接下來解釋一下各個配置的含義:

屬性 解釋
allow-forms 容許資源提交表單
allow-modals 容許資源打開模態窗口,好比window.alert()、window.confirm()、window.print()、window.prompt()
allow-orientation-lock 容許資源鎖住屏幕方向
allow-pointer-lock 容許資源使用Pointer Lock API
allow-popups 容許彈出窗口(好比window.open(), target="_blank", 或者showModalDialog()),若是這個關鍵詞沒有的話,彈出窗口將會靜默地打開失敗
allow-popups-to-escape-sandbox 容許沙箱文檔打開新窗口,而這些新窗口不須要繼承沙箱模式。
allow-presentation 容許嵌入者控制是否iframe啓用一個展現會話
allow-same-origin 容許將內容做爲普通來源對待。若是未使用該關鍵字,嵌入的內容將被視爲一個獨立的源。
allow-scripts 容許嵌入的瀏覽上下文運行腳本(但不能建立彈窗)
allow-top-navigation 容許嵌入的頁面的上下文能夠導航(加載)內容到頂級的瀏覽上下文環境(browsing context)。若是未使用該關鍵字,這個操做將不可用
allow-storage-access-by-user-activation 容許嵌入的頁面請求經過Storage Access API使用父頁面的存儲能力
allow-top-navigation-by-user-activation 容許嵌入的頁面的上下文能夠導航(加載)內容到頂級的瀏覽上下文環境(browsing context),可是隻能經過用戶手勢主動調用來初始化

關於沙箱模式的注意點

  • 當被嵌入的文檔與主頁面同源時,強烈建議不要同時使用allow-scriptsallow-same-origin,不然的話將容許嵌入的文檔經過代碼刪除sandbox屬性。雖然你能夠這麼作,可是這樣的話其安全性還不如不用sandbox。
  • 若是攻擊者能夠將潛在的惡意內容往用戶的已沙箱化的iframe中顯示,那麼沙箱操做的安全性將再也不可靠。推薦把這種內容放置到獨立的專用域中,減少可能的損失。
  • 沙箱屬性(sandbox)在Internet Explorer 9及更早的版本上不被支持

通過上面的解釋,想必知道剛開始的那個問題的答案了吧?

Tips

  1. window.frames

frames屬性是一個相似數組的對象;由於frames其實是window對象的別名,frames屬性又是能夠遍歷的,因此它是一個相似數組的對象: window.frames.length === window.length;

frames屬性的每一項是框架內的窗口,即框架內的window對象;frames屬性的每一項並非iframe的dom節點!!!若須要獲取iframe的dom節點能夠經過如下方法: frames[0].frameElement

若是有一個iframe是處於沙箱模式,而且沒有設置allow-same-origin,那麼雖然你能夠訪問到window.frames的長度爲2,可是當你獲取window.frames[1].location的時候會有這樣的錯誤:

DOMException: Blocked a frame with origin "http://127.0.0.1:3000" from accessing a cross-origin frame

配置了allow-same-origin的時候:

沒有配置allow-same-origin的時候:

  1. window.top: 頂層窗口,即最上層的窗口

  2. window.parent: 父窗口,若是一個窗口沒有父窗口,則它的parent屬性爲自身的引用;

  3. window.self: 當前窗口,即自身的引用;

參考

  1. iframe
相關文章
相關標籤/搜索