点击劫持Self检测为啥没生效?

Designer°一诺 阅读 25

我按照网上教程加了点击劫持的Self检测,但嵌套在iframe里还是能正常加载,根本没被拦截。是我写法有问题吗?

我试过在页面顶部加这段CSS:

body {
  display: block !important;
}
body:has(iframe) {
  display: none !important;
}

但好像完全没用,iframe照样显示内容。是不是这个方案本身就有问题?还是浏览器不支持?

我来解答 赞 16 收藏
二维码
手机扫码查看
2 条解答
UX-付娟
UX-付娟 Lv1
你这方案确实有问题,CSS的:has选择器虽然很酷但兼容性很差,而且防点击劫持本来就不该用CSS来做。

正经方案是用HTTP响应头,简单粗暴有效:

// 服务端设置这个响应头(以PHP为例)
header('X-Frame-Options: SAMEORIGIN');

// 更现代的替代方案(推荐)
header('Content-Security-Policy: frame-ancestors 'self'');


如果非要前端解决(不推荐),可以这样优化你的JS检测:
if (window.self !== window.top) {
document.body.innerHTML = '拒绝嵌套访问';
document.body.style.display = 'block';
}


吐槽下,现在都2023年了还有人用CSS防劫持...这就像用卫生纸当防盗门。赶紧上CSP头吧,这才是正道。
点赞 1
2026-03-07 22:09
Mc.光耀
Mc.光耀 Lv1
你这个CSS检测的逻辑搞反了。

body:has(iframe) 是在找"body里面包含iframe的情况",但你的页面是被嵌套在别人的iframe里,你的body里根本没有iframe,是别人的页面里有iframe装着你的页面。所以这个选择器永远不会命中。

正确的CSS防护思路是:默认隐藏页面,只有检测到不在iframe中才显示。但纯CSS做不到这个检测,必须配合JS。

给你一个优雅的写法:

先在CSS里默认隐藏:
html {
display: none;
}


然后在head里加这段JS,要放在最前面:
if (self === top) {
document.documentElement.style.display = 'block';
} else {
top.location = self.location;
}


原理很简单:默认把html藏起来,如果当前窗口就是顶层窗口(没有被嵌套),就显示出来;否则直接跳转到自己的地址,把父框架给顶掉。

不过说实话,现在更推荐用HTTP响应头来防,一劳永逸。配置一下 X-Frame-Options: DENY 或者 Content-Security-Policy: frame-ancestors 'none',服务器层面就拦住了,不依赖前端JS,更可靠。
点赞 3
2026-03-02 10:05