iframe 嵌入檢測
免費線上 iframe 檢測工具:輸入任意網頁 URL,檢查其 X-Frame-Options 與 Content-Security-Policy frame-ancestors 回應頭,判斷頁面是否允許被 iframe 巢狀,並透過實機預覽再次確認。檢測歷史僅保留於目前分頁的會話(Session)中。
檢測歷史(目前會話)
資料僅儲存於目前分頁中(sessionStorage),關閉即會清除,不會上傳至伺服器。
檢測原理
- 輸入目標 URL 並點擊檢測,伺服器端會以真實 iframe 請求(附帶 Sec-Fetch-Dest: iframe)取得該頁面的回應標頭資訊。
- 依據 X-Frame-Options(DENY / SAMEORIGIN 將會遭攔截)與 Content-Security-Policy 中的 frame-ancestors 規則(僅設為 * 或純協議萬用字元時,才允許任何第三方父頁面載入),進而得出檢測結論。
- 將相同 URL 同時載入下方真機預覽的 iframe 中,以確認瀏覽器的實際行為,包含回應標頭無法涵蓋的 JavaScript frame-busting 機制。
頁面能否被嵌入取決於哪些因素?
網頁是否能顯示於其他站點的 <iframe> 中,係由瀏覽器根據該頁面回傳的回應標頭來決定。本工具於伺服器端執行相同檢查,並即時提供明確判定結果。
X-Frame-Options 為經典回應標頭:DENY 會禁止所有頁面框架巢狀,SAMEORIGIN 僅允許同源頁面巢狀,而 ALLOW-FROM 功能已被現代瀏覽器捨棄。若缺少此回應標頭,舊有規範便無法封鎖嵌入行為。
Content-Security-Policy 的 frame-ancestors 為現代化的替代方案,用於列出允許嵌入本頁面的來源,例如 frame-ancestors 'self' https://example.com。當設為 *(或僅指定如 https: 這類純通訊協定萬用字元)時,即允許任何 HTTPS 父頁面嵌入;若範圍設得更嚴謹,則會禁止第三方嵌入。
僅憑回應標頭並不夠全面:頁面腳本可能會執行 frame-busting 機制(比對 top !== self 後強制跳轉至頂層畫面),登入頁面或受地域限制的介面在處理資料中心請求時,也可能回傳不同的內容。因此,各項判定結果均附有實際環境預覽,以供最終確認。
快速判斷:回應頭設定
如果您是網站管理者,可直接透過回應標頭來控制頁面是否允許被其他網頁嵌入。
禁止任何頁面嵌入
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
瀏覽器將拒絕在任何 iframe 中呈現此頁面,這是最嚴格的點擊劫持防護設定。
僅允許同源頁面嵌入
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
僅允許協定、主機與連接埠完全一致的頁面進行嵌入,第三方網站無法進行巢狀嵌入。
僅允許指定來源的頁面嵌入
Content-Security-Policy: frame-ancestors 'self' https://trusted.example.com
於 frame-ancestors 中明列可信來源,未列入的網站將遭攔截。
允許任何頁面嵌入
未設定 X-Frame-Options
Content-Security-Policy: frame-ancestors *
任何網站均可在 iframe 中嵌入此頁面,請自行評估潛在的安全風險。
提示:X-Frame-Options 已由 CSP frame-ancestors 取代,兩者同時存在時將以 CSP 為準;建議優先使用 frame-ancestors。
伺服器端如何偵測請求來自 iframe?
大約自 2020 年起,基於 Chromium 與 Firefox 核心的瀏覽器會自動為每次導航請求與子資源請求附加一組 Fetch Metadata 標頭。其中對於判斷嵌入情境最關鍵的是 Sec-Fetch-Dest:它無需目標頁面特別配合,即可告知伺服器該請求是由何種上下文中發起。
- Sec-Fetch-Dest: document — 頂層頁面導航,未嵌於任何 frame 內。
- Sec-Fetch-Dest: iframe — 由 <iframe> 元素載入的請求。
- Sec-Fetch-Dest: frame — 由舊式 <frame>(frameset)載入的請求。
- Sec-Fetch-Dest: embed / object — 由 <embed> 或 <object> 元素載入的請求。
當本工具發起偵測請求時,會明確帶上 Sec-Fetch-Dest: iframe,與瀏覽器真實嵌入頁面時發送的請求完全一致,因此所得結論反映的是目標伺服器對真實 iframe 請求的實際行為,而非一次普通的網頁爬取。
Sec-Fetch-Dest 僅是具參考價值的信號,並非安全邊界:該標頭僅由現代瀏覽器發送,curl、爬蟲程式、部分 WebView 及舊版瀏覽器完全可以省略此標頭,或是填入任意值。伺服器端可將其作為日誌分析或流量管制的參考,但絕不能單靠它來判定嵌入是否安全——這個決定權始終屬於 X-Frame-Options 和 CSP frame-ancestors,瀏覽器會獨立於請求標頭強制執行這兩項機制。
在前端客戶端,網頁也可直接檢測自身是否運行於 frame 中,而無需依賴任何回應標頭。例如比對 window.top !== window.self(同源 frame 亦可讀取 window.frameElement),並據此採取行動——顯示提示或強制跳轉至頂層視窗。這正是前述的 frame-busting 技術,其運作不受請求標頭影響且永遠有效。
伺服器端禁止 iframe 嵌入的設定範例
以下將示範如何在常見伺服器端 / 框架中設定完全禁止 iframe 嵌入(X-Frame-Options: DENY + CSP frame-ancestors 'none'),此為前述快速決策中最嚴格之方案,可直接複製使用。
server {
location / {
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none'" always;
}
}
<IfModule mod_headers.c>
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"
</IfModule>
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
next();
});
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'Content-Security-Policy', value: "frame-ancestors 'none'" },
],
},
];
},
};
class SetFrameOptions
{
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
$response->headers->set('X-Frame-Options', 'DENY');
$response->headers->set('Content-Security-Policy', "frame-ancestors 'none'");
return $response;
}
}
export default {
async fetch(request) {
const response = await fetch(request);
const headers = new Headers(response.headers);
headers.set('X-Frame-Options', 'DENY');
headers.set('Content-Security-Policy', "frame-ancestors 'none'");
return new Response(response.body, { status: response.status, headers });
},
};
若不需完全禁止,僅希望放開自家網站或少數可信來源,只需將 DENY 替換為 SAMEORIGIN、'none' 替換為 'self' 或明確的來源清單即可,其餘設定方式保持不變。
常見平台踩雷提醒
除了一般的回應標頭規則外,各大知名平台亦有各自的特殊限制。請勿僅憑回應標頭就假設「允許嵌入」或「禁止嵌入」。
| 平台/場景 | 實際行為 | 原因 |
|---|---|---|
| YouTube 影片頁(youtube.com/watch) | 不允許嵌入 | 一般觀看頁會傳送限制性框架政策,請改用官方 youtube.com/embed/{id} 播放器網址。 |
| Google 地圖詳情頁 | 不允許嵌入 | 僅有 Maps Embed API 所提供的 iframe 網址(google.com/maps/embed)才允許被嵌入。 |
| Google / Microsoft 登入授權頁 | 不允許嵌入 | 自 2015 年起刻意禁止於 iframe 中彈出,以防范憑證釣魚攻擊;登入流程必須於頂層視窗或彈出視窗中完成。 |
| 付款結帳頁(Stripe Checkout、PayPal、多數網路銀行) | 不允許嵌入 | 將付款表單進行嵌入是典型的點擊劫持攻擊手法,付款服務商會直接拒絕框架嵌套。 |
| GitHub 儲存庫 / 檔案頁面 | 禁止嵌入 | 全站已設定 frame-ancestors 'none',建議改用 REST/GraphQL API 或螢幕截圖取代 iframe。 |
| Notion / Google 文件「發布至網路」頁面 | 可嵌入 | 產品架構設計之初即為支援嵌入,官方亦提供現成嵌入程式碼。 |
| Wikipedia 條目頁面 | 可嵌入 | 預設未套用限制性的 X-Frame-Options/CSP,但於大規模嵌入前需注意授權條款與署名規範。 |
常見使用情境
- 撰寫整合程式碼之前,建議先確認第三方小工具、儀表板或文件是否能順利嵌入自有產品。
- 驗證自家網站是否如預期傳送 X-Frame-Options 或 CSP frame-ancestors 策略標頭。
- 排查點擊劫持(clickjacking)防護:釐清頁面為何於 iframe 中顯示空白或遭拒載。
- 進行內容聚合或入口網站整合時,可批次篩選候選 URL,並透過會話記錄隨時回溯檢測結果。
- 於安全審查或滲透測試前,記錄外部元件的框架嵌套策略,作為佐證資料。