X-Frame-Options 设置后为什么页面还是能被嵌入 iframe?
我最近在项目里加了 X-Frame-Options 响应头,设成了 DENY,但发现别人还是能用 iframe 把我的页面嵌进去,完全没生效。是我设置方式不对吗?
后端是用 Express 写的,代码大概是这样:
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'DENY');
next();
});
本地测试时用另一个 HTML 文件写了 iframe,确实还能加载我的页面,控制台也没报错。这头不是应该直接阻止加载吗?是不是浏览器兼容问题,还是我漏了什么配置?
最常见的原因是你的项目里可能同时配置了 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 来控制,毕竟这是现代标准。可以试试把代码改成下面这样,把两个头都统一一下,确保万无一失:
你可以先去 Network 面板确认下响应头到底发了啥,这是最直接的判断方式。如果发现确实有 CSP 且允许了嵌套,把 CSP 改成 'none' 就能彻底解决问题了。