iframe
被用于将一个网页嵌套在另一个网页中,有的时候这会带来一些安全问题,这时我们就需要一些防嵌套操作了。
本文分为俩部分,一部分讲解如何检测或者禁止嵌套操作,另一部分讲解如何从嵌套中跳出。
末尾放了正在使用的完整代码,想直接用的可以拉到最后。
效果
当存在嵌套时会出现一个蒙版和窗口,提示用户点击。 点击后会在新窗口打开网站页面。
嵌套检测
设置响应头
响应头中有一个名为X-Frame-Options
的键,可以针对嵌套操作做限制。
它有3个可选值:
DENY:拒绝所有
SAMEORIGIN:只允许同源
ALLOW-FROM origin:指定可用的嵌套域名,新浏览器已弃用
后端检测(以PHP为例)
通过获取$_SERVER
中的HTTP_REFERER
和HTTP_SEC_FETCH_DEST
值,可以判断是否正在被iframe嵌套
// 如果不是iframe,就为空的字符串 $REFERER_URL = $_SERVER['HTTP_REFERER'];
// 资源类型,如果是iframe引用的,会是iframe
SEC_FETCH_DEST = _SERVER['HTTP_SEC_FETCH_DEST'];// 默认没有被嵌套
$isInIframe = false;if (isset($_SERVER['HTTP_REFERER'])) {
refererUrl = parse_url(_SERVER['HTTP_REFERER']);
refererHost = isset(refererUrl['host']) ? $refererUrl['host'] : '';if (!empty(refererHost) && refererHost !== $_SERVER['HTTP_HOST']) {
$isInIframe = true;
}
}
// 这里通过判断$isInIframe是否为真,来处理嵌套和未嵌套执行的动作。
if($isInIframe){
....
}
前端检测(使用JavaScript)
通过比较window.self
(当前窗口对象)和window.top
(顶层窗口对象)可以判断是否正在被iframe嵌套
if (window.self !== window.top) {
// 检测到嵌套时该干的事
}
从嵌套中跳出
跳出只能是前端处理,如果使用了PHP等后端检测,可以直接返回前端JavaScript代码,或者HTML的A标签设置转跳。
JavaScript直接转跳(不推荐)
不推荐是因为现在大多浏览器为了防止滥用,会阻止自动弹出新窗口。
window.open(window.location.href, '_blank');
A标签点击转跳(较为推荐)
当发生了用户交互事件,浏览器就不会阻止转跳了,所以这是个不错的方法。
<a href="https://www.9kr.cc" target="_blank">点击进入博客</a>
JavaScript+A标签(最佳方法)
原理是先使用JavaScript检测是否存在嵌套,
如果存在嵌套,再使用JavaScript加载蒙版和A标签,引导用户点击。
这个方法直接查看最后一节。
正在使用的方法
也就是上一节说的JavaScript+A标签。
先给待会要显示的蒙版和A标签窗口设置样式
/* 蒙版样式 /
.overlay1 {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5); / 半透明背景颜色 /
z-index: 9999; / 确保蒙版位于其他元素之上 */
display: flex;
align-items: center;
justify-content: center;
}/* 窗口样式 */ .modal1 { background-color: #fff; padding: 20px; border-radius: 5px; }</code></pre></div></div><p>然后是检测和加载蒙版+A标签的JavaScript代码</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">if (window.self !== window.top) { // 创建蒙版元素 var overlay = document.createElement('div'); overlay.className = 'overlay1'; // 创建窗口元素 var modal = document.createElement('div'); modal.className = 'modal1'; // 创建A标签元素 var link = document.createElement('a'); link.href = 'https://www.9kr.cc'; link.target = '_blank'; // 在新窗口中打开链接 link.innerText = '点击进入博客'; //link.addEventListener('click', function(event) { // event.preventDefault(); // 阻止默认链接行为 // alert('Test'); //}); // 将A标签添加到窗口元素中 modal.appendChild(link); // 将窗口元素添加到蒙版元素中 overlay.appendChild(modal); // 将蒙版元素添加到body中 document.body.appendChild(overlay);
}
博客的话,只需要在主题上设置自定义CSS
和自定义JavaScript
即可