如何防止嵌套页面被点击劫持?X-Frame-Options和CSP设置无效?

开发者世杰 阅读 22

最近在开发仪表盘页面时,发现嵌套的表单页面被恶意网站用iframe嵌入,导致用户误操作点击劫持。我尝试在服务器配置中设置了X-Frame-Options: SAMEORIGIN,并在CSP头里写了:

Content-Security-Policy: frame-ancestors 'none'

但测试时发现页面仍然能被其他域名的iframe加载,控制台也没有报错提示。是不是设置方法有误?或者还有其他防护措施需要配合使用?

我来解答 赞 24 收藏
二维码
手机扫码查看
2 条解答
FSD-瑞玲
X-Frame-Options 和 frame-ancestors 不能同时生效,浏览器会优先用后者,但如果你的服务器配置没生效,可能是被覆盖了。检查响应头到底有没有正确返回,可以用
res.setHeader('Content-Security-Policy', "frame-ancestors 'self';");
这种方式在后端强制设置,别依赖配置文件。还有,清下浏览器缓存再测,有时候改了头信息没刷新导致误判。
点赞 2
2026-02-10 02:12
程序猿熙炫
这个问题我之前也踩过坑,你设置的方向是对的,但可能被某些细节坑了。首先 X-Frame-Options 和 CSP 的 frame-ancestors 不能同时都设,因为它们是互斥的,浏览器会优先处理 CSP,所以如果 CSP 写错了,X-Frame-Options 就等于白搭。

frame-ancestors 要生效,必须确保头信息拼写完全正确,而且是服务端返回的响应头里带上的。很多人在 Nginx 或 Apache 里加了 header,但忘了检查实际响应中有没有真正输出出来。你可以打开浏览器开发者工具,看 Network 面板里目标页面的 Response Headers,确认是否真的有:

Content-Security-Policy: frame-ancestors 'none';

注意这里单引号是合法的,但有些服务器配置可能会把它解析成字符串,导致语法错误,CSP 不生效。我的做法是直接用双引号包裹值,在 Nginx 里这样写:

add_header Content-Security-Policy "frame-ancestors 'none';";

另外,如果你用了框架比如 React、Vue 做前端路由,注意后端要确保所有入口路径(尤其是 HTML 页面)都带上这个头,否则静态资源或 API 接口没头也没用。

还有一个常见问题是测试方式不对。你得用一个外部域名的页面写 iframe 来试,而不是本地 file 协议或者同域测试,那样本来就能加载。可以临时起个别的域名或用 http-server 模拟不同源。

最后建议只保留 CSP 的 frame-ancestors,删掉 X-Frame-Options,避免冲突。现代浏览器都支持 frame-ancestors,它比 X-Frame-Options 更灵活也更优先。

实在不行可以在 JS 里加一层防御:

if (window.self !== window.top) {
window.top.location = window.self.location;
}


虽然不完美,但能防住大部分简单劫持。先查响应头有没有正确返回,再一步步排除,基本都能解决。
点赞 4
2026-02-10 01:00