应始终为 target="_blank" 添加 rel="noopener" 以防止 opener abuse 攻击,因其可切断 window.opener 引用、消除安全风险与性能隐患,且现代审计工具将其缺失标为严重问题。

直接加 target="_blank" 不够,不加 rel="noopener" 会有安全风险和性能问题
为什么 target="_blank" 默认不安全
当页面用 target="_blank" 打开新页面时,新页面会通过 window.opener 访问原页面的 window 对象——这意味着它能调用 window.opener.location = 'https://evil.com' 反向劫持你的页面(即“opener abuse”)。Chrome、Firefox 等现代浏览器已默认将跨源 opener 设为 null,但同源场景下仍存在风险,且旧版浏览器完全不受限。
实操建议:
- 始终搭配使用
rel="noopener"(推荐)或rel="noreferrer" -
rel="noopener":切断window.opener引用,保留Referer头 -
rel="noreferrer":同时移除window.opener和Referer头(适合不想泄露来源的场景) - 不要写成
target="_blank" rel="noreferrer noopener"——noopener已隐含noreferrer的 opener 行为,二者并列冗余(尽管浏览器兼容)
target="_blank" 在不同浏览器中的行为差异
虽然规范定义 target="_blank" 应打开新标签页(非窗口),但实际取决于用户浏览器设置和系统偏好:
立即学习“前端免费学习笔记(深入)”;
- Chrome / Edge:默认新开标签页;若用户禁用标签页、启用弹窗拦截,可能退化为新窗口
- Safari:在 iOS 上强制在新标签页中打开(不可配置);macOS 上受「在新窗口中打开链接」系统选项影响
- Firefox:遵循用户设置,可通过
browser.link.open_newwindow配置项控制(值为 1/2/3) - 没有 JS 干预时,无法强制“新开窗口”(
window.open()才能控制尺寸、位置等)
常见错误写法与修复
这些写法看似能用,但埋了坑:
- 只写
<a href="..." target="_blank"></a>→ 缺少rel,存在安全漏洞 - 写成
target="_blank_"或target="blank"→ 浏览器当作命名窗口处理,可能复用已有标签页,导致意外覆盖 - 在 Vue/React 中动态绑定:
:target="isExternal ? '_blank' : '_self'"却忘了同步绑定:rel="isExternal ? 'noopener' : ''"→ 条件缺失导致漏掉防护 - 用
target="_blank"链接到同域页面(如内部文档)→ 仍需rel="noopener",因为同源下window.opener完全可读写
真正安全的写法就这一行:<a href="https://example.com" target="_blank" rel="noopener">Link</a>。别省略 rel,哪怕只是个静态链接——这个细节在审计工具(如 Lighthouse)里直接标为「严重」,而且一旦上线,攻击面就长期存在。



















