你可能忽略的HTML安全漏洞:rel=’noopener’深入理解
现如今,网络安全已经成为我们不可忽视的一个问题。不管是大厂还是小作坊,每一位开发者都会有这方面的考虑。然而,我们通常会花费大量的时间和精力在后端服务上,对于前端来说,可能会忽视这方面的考虑。
今天我们要分享的,是一个经常被忽略但是却非常重要的知识点——HTML 中的 rel="noopener"
。
这是 a
标签上的一个属性,你可能见过也可能压根儿就不知道 a 标签竟然还有这样一个属性。这个属性看起来或许无关紧要,但是在网页安全性方面却起着不可或缺的作用。即使你是一枚有经验的前端开发者,你可能也没有深入考虑过这个属性的重要性,更不用说在项目中主动去实际应用了。
在今天的分享中,我们会深入讨论 rel="noopener"
这个属性,通过一个具体的示例,向你展示它的作用。
无论你是前端小白,还是从事前端开发多年的老司机,我相信你都会从这篇文章中 get 到一些启发。
现在,就让我们开始吧~
1. 深入一下 ~
在 HTML 中,rel
属性定义了当前文档与被链接文档之间的关系。在文档上下文中,noopener
是一个很重要的链接类型值。当我们在一个 a
标签中使用 target="_blank"
属性在新的浏览器窗口或标签页中打开一个链接时,rel="noopener"
的使用就变得尤其重要。
1.1 什么是 rel="noopener"
?
rel="noopener"
是一个安全性措施,它的作用是用来防止新打开的页面通过 window.opener
对象访问原始页面。在新打开的页面中,可以通过 window.opener
对象引用打开它的原始页面,而这,就会导致一些潜在的安全性问题。当 rel="noopener"
被设置后,window.opener
在新页面中的值将为 null
。
1.2 为什么说 rel="noopener"
是重要的?
站在安全性的角度来看,如果你网站上的链接打开了一个外部地址,那么这个外部网站是有可能通过 window.opener
来改变原始页面的内容或 URL 的,这就有可能会导致所谓的”Tabnabbing“攻击(网站钓鱼攻击)——直到目前为止,这种手段仍然非常常见。
添加 rel="noopener"
就可以有效地防止这种攻击。
除此之外,rel="noopener"
还能提升页面性能你信吗?
相信许多小伙伴都会问,就这么个属性咋还跟页面性能有关呢?!如果你知道的话,那我不得不说你知识面是真的宽~
不知道的小伙伴看过来,听我跟你 battle battle、
当一个新的页面被打开时,浏览器通常会把原始页面保留在内存中,这能方便我们在新页面访问 window.opener
对象。但是当设置了 rel="noopener"
后,由于新页面无法访问 window.opener
,浏览器就可以将原始页面从内存中清除,这样,内存资源就被释放了。
有木有豁然开朗的赶脚~
不过呢,在一些比较老旧的浏览器中是不支持这是属性的,但是大家放心,多数现代浏览器都已经支持了 rel="noopener"
属性,你可以放心大胆的用。

还有一点,为了在浏览器中提供相同的安全性,你还可以使用 rel="noreferrer"
属性,这个属性除了阻止新页面访问 window.opener
对象外,还会阻止发送 HTTP Referer 头。
2. 一个栗子
假设一个场景,我们通过原始页面中的一个链接打开了一个外部网站,然后在外部网站中篡改原始页面的 URL。
<!-- 新标签页打开外部网站 external-website -->
<a href="http://external-website.com" target="_blank">Go to external website</a>
然后,我们在外部网站上来试一下篡改原始页面的 URL:
if (window.opener) {
// 原始页面被重定向到恶意站点
window.opener.location = 'http://malicious-website.com';
}
仔细观察可以发现,这两个站点不在同一个域名下,也就是说,即使浏览器有同源策略,也不能避免原始页面被篡改!

所以你知道了吧,同源策略不会阻止新页面通过 window.opener
对象访问或操控原始页面。