iframe無法訪問頁面


背景

在一些場景下,我們的網站需要通過iframe標簽嵌入第三方廠家的頁面,這時候就得通過iframe標簽去引入需要嵌入網頁的網址了

案例

例如,2月15日是元宵節,為了慶祝元宵,我們需要在主站上線活動頁,這個活動頁剛好是一個第三方網站(歐陽修的一首詞),我們需要把他嵌入到主站中:

iframe-load-url-01.png

主站設計圖如下:

iframe-load-url-02.png

主站實現代碼如下:

<div class="container">
  <h3>萬家燈火,共聚團圓 </h3>
  <p><em>正月十五元宵節</em></p>
  <div class="ad">
    <iframe src="https://www.zzcyes.com/yuanxiao/ci.html"></iframe>
  </div>
</div>

問題

把代碼提交之后,打開我們的主站,效果卻變成了這樣:

iframe-load-url-03.png

查看控制台,有以下報錯信息:​
Refused to display 'https://www.zzcyes.com/' in a frame because it set 'X-Frame-Options' to 'deny'.

iframe-load-url-04.png

控制台說在ifame嵌入的第三方網站拒絕了我們的訪問,因為它把X-Frame-Options設置成了deny

X-Frame-Options

MDN對它的解釋如下:

The X-Frame-Options HTTP 響應頭是用來給瀏覽器 指示允許一個頁面 可否在 <frame>, <iframe>, <embed> 或者 <object> 中展現的標記。站點可以通過確保網站沒有被嵌入到別人的站點里面,從而避免 clickjacking 攻擊。

換一句話說,如果設置為 deny,不光在別人的網站 frame 嵌入時會無法加載,在同域名頁面中同樣會無法加載。另一方面,如果設置為sameorigin,那么頁面就可以在同域名頁面的frame中嵌套。

  • deny表示該頁面不允許在 frame 中展示,即便是在相同域名的頁面中嵌套也不允許。
  • sameorigin表示該頁面可以在相同域名頁面的 frame 中展示。
  • allow-from _uri_表示該頁面可以在指定來源的 frame 中展示。

解決方案

知道X-Frame-Options的含義后,那么我們只需將X-Frame-Options的值設為sameoriginallow-from uri即可。由於第三方頁面是通過nginx部署的,因此,我們需要配置 nginx 發送 X-Frame-Options 響應頭,把sameoriginallow-from uri添加到 "http","server"或者 "location"的配置中(保存好配置后記得重啟nginx -s reload)

X-Frame-Options:sameorigin

如果主站和嵌入的第三方網頁在同一個域中,可以把add_header X-Frame-Options sameorigin這一行,添加到nginx配置中:

 server {
  #listen       80;
  listen 443 ssl; // 主站是https協議
  server_name www.zzcyes.com;
  add_header X-Frame-Options sameorigin;
	// 省略其它配置
  ...
}

X-Frame-Options:allow-from uri

如果主站和嵌入的第三方網頁不在同一個域中,可以把add_header X-Frame-Options "ALLOW-FROM url"這一行,添加到nginx配置中去。這里的url是指你主站的url,也就是嵌入iframe的網頁地址,不是iframe上訪問的網址。

假設主站網址為https://www.zzcyes.com,配置如下:add_header X-Frame-Options "ALLOW-FROM https://www.zzcyes.com"

若有多個主站需要嵌入第三方網頁,則需要用逗號分隔多個主站的網址:
add_header X-Frame-Options "ALLOW-FROM https://www.zzcyes.com,http://www.zzcyes.com"

 server {
  #listen       80;
  listen 443 ssl; // 主站是https協議
  server_name www.zzcyes.com;
  add_header X-Frame-Options "ALLOW-FROM https://www.zzcyes.com";
  // 多個用逗號分隔
  #add_header X-Frame-Options "ALLOW-FROM https://www.zzcyes.com,http://www.zzcyes.com";
  ...
}

注意:當按以上配置允許iframe展示的網站時,控制台打印如下錯誤:
Invalid 'X-Frame-Options' header encountered when loading 'https://www.zzcyes.com/': 'ALLOW-FROM https://www.zzcyes.com'is not a recognized directive. The header will be ignored.

iframe-load-url-05.png

控制台打印說我設置的標頭X-Frame-Options不生效,我反復檢查了下nginx的配置,確實沒有問題。於是想了下會不會瀏覽器版本的,是不是不支持allow-from這個語法,果然,在mdn瀏覽器兼容性的表上查到了,果然不支持(chrome瀏覽器)allow-from這個語法,那么這種方案(在chrome瀏覽器上)就行不通了

iframe-load-url-06.png

Content-Security-Policy

如果主站和嵌入的第三方網頁不在同一個域中,通過設置X-Frame-options的值為allow-from url這個方法,顯然在大部分瀏覽器上都不支持(IE和火狐除外)。同樣在mdn對X-Frame-Options描述下有這么一段話:

The added security is only provided if the user accessing the document is using a browser supporting X-Frame-Options. Content-Security-Policy HTTP 頭中的 frame-ancestors 指令會替代這個非標准的 header。CSP 的 frame-ancestors 會在 Gecko 4.0 中支持,但是並不會被所有瀏覽器支持。然而 X-Frame-Options 是個已廣泛支持的非官方標准,可以和 CSP 結合使用。

這里引出了Content-Security-Policy,具體用法請到MDN查閱。

文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM