rel="noopener"防范什么攻击_HTML新窗口安全隐患

作者:袖梨 2026-06-16
rel="noopener"防止Tabnabbing攻击,核心是强制新页面window.opener为null,切断其通过window.opener劫持原页面的能力;不加它,target="_blank"会使新页面获得对原页面的完全控制权。

rel="noopener" 防止的是 Tabnabbing 攻击,核心是阻断新标签页通过 window.opener 劫持原页面 —— 不加它,target="_blank" 就等于主动交出控制权。

为什么 target="_blank" 默认危险?

浏览器对 target="_blank" 的默认行为是:让新页面的 window.opener 指向原始页面的 window 对象。这不是 bug,是规范允许的。

这意味着,哪怕你跳转到一个完全不同的域名(比如 https://evil.example),它也能执行:

  • window.opener.location.href = "https://phish.example/login" —— 瞬间把你的登录页替换成钓鱼页
  • window.opener.document.write(...) —— 直接覆盖你刚离开的 DOM
  • window.opener.postMessage(...) —— 如果原页面监听了 message,可能触发未授权操作

跨域限制在这里不生效 —— window.opener 访问本身不要求同源,只是后续读写 DOM 或 location 时才受同源策略约束(而 location 跳转根本不受限)。

立即学习“前端免费学习笔记(深入)”;

rel="noopener" 到底做了什么?

它强制将新页面的 window.opener 设为 null,不是“禁用”或“忽略”,而是从源头切断引用。

  • 新页面执行 window.opener 得到 null,所有基于它的操作直接报错或静默失败
  • 现代浏览器(Chrome 64+、Firefox 79+、Safari 12.1+)已将 noopener 作为 target="_blank" 的隐式默认行为,但显式声明更可靠,且兼容旧版
  • rel="noopener"rel="noopener noreferrer" 在多数浏览器中效果一致:都设 window.opener = null,也都抑制 Referer;但 noreferrer 是额外声明,语义更明确

什么时候必须加?哪些情况可以不加?

只要链接目标不可信(外部站点、用户生成内容、第三方平台),就必须加 rel="noopener"

  • 典型场景:<a href="https://twitter.com" target="_blank" rel="noopener">Twitter</a>
  • 例外极少:仅当你**完全控制新页面代码**,且**明确需要与 opener 通信**(如内部微前端子应用),才可省略;此时应自行实现安全的 postMessage 协议,而非依赖裸露的 window.opener
  • WordPress 等 CMS 自 5.6.0 起默认注入 rel="noopener",但已移除 noreferrer —— 因为 noopener 在主流浏览器中已附带 Referer 抑制效果

容易被忽略的关键点

很多人以为加了 rel="noopener" 就万事大吉,但实际还有两个盲区:

  • 如果链接同时有 rel="nofollow",别写成 rel="noopener nofollow" 之类拼接错误 —— 多个值必须用空格分隔,且不能重复,否则部分解析器会丢弃整个 rel
  • 动态插入的链接(比如 JS 生成的 document.createElement('a'))不会自动获得 rel="noopener",必须手动设置:a.rel = 'noopener'
  • rel="noopener"window.open() 无效 —— 它只作用于 <a> 标签;JS 打开窗口需用 window.open(url, '_blank', 'noopener')(注意第三个参数是 features 字符串,不是 rel)

相关文章

精彩推荐