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

一红爱 阅读 40

我在项目里加了 X-Frame-Options: DENY 响应头,但本地开发时用 iframe 引入自己的页面居然还能加载出来,是不是我配错了?

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

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

浏览器控制台也没报错,但 iframe 里内容正常显示,这不科学啊……

我来解答 赞 19 收藏
二维码
手机扫码查看
2 条解答
圣贤的笔记
这个问题其实挺常见的,十有八九是浏览器缓存搞的鬼。

你想想看,你最开始可能没加这个 header 的时候已经访问过页面了,浏览器把响应缓存下来了。后来加了中间件,但浏览器直接从缓存里拿旧响应,根本没发请求到你后端,所以 header 当然没生效。

先试一下:打开浏览器的无痕模式或者彻底清除缓存,再试一次 iframe,如果这时候不能加载了,那就确认是缓存问题。

如果不是缓存,那很可能是中间件顺序的问题。你检查一下代码里静态文件中间件的位置:

// 错误的顺序:静态文件直接返回,不经过你的 header 中间件
app.use(express.static('public')); // 这货直接返回文件,跳过了后面的中间件
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'DENY');
next();
});

// 正确的顺序
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'DENY');
next();
});
app.use(express.static('public'));


Express 的中间件是按顺序执行的,如果静态文件中间件已经返回了响应,代码根本不会走到你设置 header 的地方。

还有一个可能的坑:如果你的页面是通过 file:// 协议打开的,或者 iframe 里的 src 是本地文件路径,某些浏览器对这种情况的 X-Frame-Options 处理不太一致。

你先把缓存清了,然后把中间件顺序调换一下试试,基本就能搞定。
点赞
2026-03-11 19:07
书生シ爱娜
你本地开发用的可能是 localhost 或 127.0.0.1,现代浏览器对同源 iframe 嵌套有宽松策略,不会严格拦截 X-Frame-Options。
换成真实域名(比如改 hosts 指向 127.0.0.1)再测,或者加 res.setHeader('Content-Security-Policy', 'frame-ancestors 'none''),后者更可靠。

搞定。
点赞 3
2026-02-26 13:00