問題
原有 a.com/hello
當中嵌入 a.com/world
iframe 本身沒問題,後來因為公司政策改變需要調整為 hello.a.com
與 world.a.com
而原有的 a.com/hello
以及 a.com/world
拜訪後會 redirect 到 hello.a.com
與 world.a.com
當中,而在這中間發現 iframe 失效並嘗試進行解決。
依照同源政策規則,調整為 hello.a.com 與 world.a.com 視為不同源,因此需要額外配置。
同源定義
所謂同源是指兩份網頁具備相同協定、埠號 (如果有指定) 以及主機位置,下表提供了一些例子展示那些來源和 http://store.company.com/dir/page.html
屬於同源:
URL | Outcome | Reason |
---|---|---|
http://store.company.com/dir2/other.html |
同源 | |
http://store.company.com/dir/inner/another.html |
同源 | |
https://store.company.com/secure.html |
不同源 | 協定不同 |
http://store.company.com:81/dir/etc.html |
不同源 | 埠號不同 |
http://news.company.com/dir/other.html |
不同源 ✅ | 主機位置不同 ✅ |
出錯點
Refused to display 'https://world.a.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
問題思路與解法
X-Frame-Options
X-Frame-Options 提供三種參數,並且功能如下
DENY
表示網頁無論如何都無法被嵌入到 frame 中,即使於相同網域內嵌入也不允許。
SAMEORIGIN
唯有當符合同源政策下,才能被嵌入到 frame 中。
ALLOW-FROM uri
已棄用
唯有列表許可的 URI 才能嵌入到 frame 中。新版瀏覽器已不再支援此指令。
其中 SAMEORIGIN 為預設參數
原本是採用 ALLOW-FROM
但已經被棄用,官方則推薦使用 content-security-policy 當中得 frame-ancestors 作為替代:
The Content-Security-Policy HTTP header has a frame-ancestors directive which you can use instead.
初探 Content-Security-Policy (CSP)
MDN 說明
MDN 延伸說明
iframe:frame-ancestors
frame-ancestors
指定可能嵌入页面的有效父项 <frame>
、<iframe>
、<object>
或 <embed>
。
這邊應該跟 browser 告知加入幾個 allow 項目:
self
*.a.com //支持 wildcard 配置
*.google-analytics.com // GA
*.googletagmanager.com // GTM
Nuxt 2 配置
在要被嵌套的服務(這邊是 a.com/world)下 nuxt.config.js
當中配置相關 csp:
export default {
render: {
csp: {
policies: {
'script-src': [
"'self'",
"'unsafe-inline'",
'*.a.com',
'*.google-analytics.com',
'*.googletagmanager.com',
],
'frame-ancestors': [
"'self'",
'*.a.com',
'*.google-analytics.com',
'*.googletagmanager.com',
],
}
}
},
}
Nuxt3
需要額外配置組件 Nuxt Security