X-Frame-Options 设置后为什么页面还是能被嵌入 iframe?

UP主~邦威 阅读 10

我最近在项目里加了 X-Frame-Options 响应头,设成了 DENY,但发现别人还是能用 iframe 把我的页面嵌进去,完全没生效。是我设置方式不对吗?

后端是用 Express 写的,代码大概是这样:

app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'DENY');
  next();
});

本地测试时用另一个 HTML 文件写了 iframe,确实还能加载我的页面,控制台也没报错。这头不是应该直接阻止加载吗?是不是浏览器兼容问题,还是我漏了什么配置?

我来解答 赞 6 收藏
二维码
手机扫码查看
1 条解答
ლ恩硕
ლ恩硕 Lv1
嘿,别慌,代码逻辑其实没啥大问题,这种情况我也遇到过,通常都是这几个坑。

最常见的原因是你的项目里可能同时配置了 Content-Security-Policy (CSP),或者用了像 helmet 这类中间件。因为 CSP 的优先级比 X-Frame-Options 高,如果响应头里同时存在 CSP 的 frame-ancestors 指令,浏览器就会直接听 CSP 的,把你设置的 X-Frame-Options 无视掉。你可以打开浏览器的开发者工具,切到 Network 面板,点开那个请求看看 Response Headers,确认下到底有没有发出去,以及有没有 Content-Security-Policy 这个头。

另一个可能是浏览器缓存太顽固了。有时候你改了后端代码,浏览器还死命用缓存的旧响应。你可以试试强制刷新,或者在 iframe 的 src 地址后面加个随机参数,比如 ?t=Date.now(),确保它拿到的是最新的响应。

如果确实是因为 CSP 冲突导致的,建议直接用 CSP 来控制,毕竟这是现代标准。可以试试把代码改成下面这样,把两个头都统一一下,确保万无一失:

app.use((req, res, next) => {
// 先移除可能存在的旧设置,防止冲突
res.removeHeader('X-Frame-Options');

// 使用 CSP 的 frame-ancestors 指令,'none' 表示完全禁止被嵌套
res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");

// 为了兼容老浏览器,还是可以顺手带上 X-Frame-Options
res.setHeader('X-Frame-Options', 'DENY');

next();
});


你可以先去 Network 面板确认下响应头到底发了啥,这是最直接的判断方式。如果发现确实有 CSP 且允许了嵌套,把 CSP 改成 'none' 就能彻底解决问题了。
点赞 1
2026-03-04 12:16