防止网页被其他网页iframe嵌套的思考与实现
一、 今天接到一个消息,说我们的登录页面被其他网页嵌套了,不能让其他网页嵌套我们的页面;
二、 风险验证措施:
- 无法跨域获取iframe页面内DOM元素
window.onload=function(){
var iframe = document.getElementsByTagName("iframe")[0];
var win = iframe.contentWindow; // 通过contentWindow获取ifame子页面的window窗体对象。(不允许跨域名访问)
var iframeDocument = iframe.contentWindow.document;
var input1 = iframeDocument.getElementById("id1");
input1.onblur = function() {
console.log(input1.value)
}
}
复制代码
- 监听按键信息:
- 当用户点击不在非iframe区域时,能被外部的document监听到;
document.onkeydown=function(e){
var keyNum=window.event?e.keyCode:e.which;
console.log(keyNum)
}
复制代码
- 当用户点击在iframe嵌套的网页里面,不会被外部的document监听,而是iframe的
contentWindow.document
对象,但是非同域名网页,无法获取iframe子页面的winodw窗体对象;
var iframe = document.getElementsByTagName("iframe")[0];
var win = iframe.contentWindow;
if(win){
var iframeDocument = iframe.contentWindow.document;
iframeDocument.addEventListener("keydown",function(e){
var keyNum=window.event?e.keyCode:e.which;
console.log("iframe-----"+keyNum)
})
}
复制代码
三、小结
虽然网页无法获取非同域名下的内嵌网页的DOM相关信息,但是假如用户习惯了在某个非官方的登入入口进入,当该非官方的页面某天更改代码,假设前几次进入的是一个伪造的界面(钓鱼网站),之后登陆出错后再切成iframe,用户信息就会被盗取,所以有这个风险,参考baidu、youku、youtube都有做这个处理;
Refused to display 'https://youku.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
四、处理
参考文章:
- 前端方法:
if (window.top != window.self) {
// top.location.href = "http://192.168.57.1:8023/";
console.log('被嵌套')
alert("dosth")
}
复制代码
评价: 可以有多种方式绕开,不建议这样做,比如:
document.write('<iframe seamless sandbox security="restricted" id="url_mainframe" frameborder="0" scrolling="yes" name="main" src="http://192.168.57.1:8023/" style="height:100%; visibility: inherit; width: 100%; z-index: 1;overflow: visible;"></iframe>');
复制代码
- 网上很多文章提及的Meta标签加
X-FRAME-OPTIONS
属性,通过google搜索meta
和X-FRAME-OPTIONS
关键字,发现该方法已经被弃用了。 X-FRAME-Options in the meta tag
来自2016年的邮件:
#摘要
当存在于
<meta>
标签内时,'X-Frame-Options'将被忽略(例如<meta http-equiv =“X-Frame-Options”contents =“DENY”>
)。它将继续作为HTTP标头支持。
#动机
我们目前尝试通过在解析标记时取消页面加载并导航到空白页面来支持
<meta>
标记内的X-Frame-Options
。这有点功能,但不完全是可靠的保护。
实际上,我们所有的XFO实现都有些不可靠,因为它们都是在Blink中实现的。我们正在努力将其迁移到浏览器进程,但如果我们需要支持
<meta>
实现,那将很难干净利落。我们要么需要Blink和//内容的实现,要么我们需要另一个IPC。
我更愿意删除功能。
- 建议后端通过添加响应头的方法实现,不做赘述,直接看MDN文档: X-Frame-Options 响应头
值得注意的是X-Frame-Options 有三个值,它们不止约定是否同域名,还约定了同协议,也就是说假如设定了属性为SAMORIGIN
,访问的父网页网址与内嵌网页的网址http协议应该要要一致(父网页为http,子网页协议为https,也无法访问;但是当父网页为https,子网页为http的情况,未做验证)
DENY
表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
SAMEORIGIN
表示该页面可以在相同域名页面的 frame 中展示。
ALLOW-FROM uri
表示该页面可以在指定来源的 frame 中展示。
五、检验和结论
-
因为是后端添加HTTP响应头的方法,所以浏览器应该不会出现兼容性的问题,不过照常做了简单测试,PC端测试了Chrome,UC,FireFox,Opera,百度,QQ,360,IE11,移动端测试了手机QQ,都符合预期;
-
通过后端添加HTTP响应头的方法实现避免网页被嵌套的结果,在控制台报的错误,与嵌套
Youtube
与youkun
效果一致:
Refused to display 'https://youku.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
;