target="_blank"必须配rel="noopener noreferrer",否则新页面可通过window.opener劫持原页、清空dom或导致卡顿;noopener切断控制链,noreferrer防referer泄露,二者缺一不可且须小写无空格。

点击链接后页面跳转失控?先看 target 值是否合理
多数人加 target="_blank" 只为新开页,却没意识到它默认共享 opener,导致新页能用 window.opener 反向控制原页面——这是安全漏洞的根源,不是“功能太强”,而是没配对处理。
常见错误现象:target="_blank" 单独使用时,新打开的页面可通过 window.opener.location = 'https://evil.com' 劫持原页(即“opener redirect”攻击);尤其在用户点击不可信链接(如评论区、UGC 内容)时风险极高。
-
target="_blank"必须搭配rel="noopener"(现代浏览器)或rel="noopener noreferrer"(兼顾 SEO 与兼容性) - IE 不支持
rel="noopener",但 IE 也不支持target="_blank"的 opener 操控,所以无需额外降级处理 - 若需 JavaScript 动态开窗,应改用
window.open(url, '_blank', 'noopener=yes'),而非依赖a标签
rel="noopener" 真的能防所有 opener 风险?
不能。它只切断 window.opener 引用,但不阻止 rel="noreferrer" 所影响的 Referer 头——这两者解决的是不同层面的问题:前者是 JS 层面的 DOM 控制权,后者是网络请求层面的来源泄露。
使用场景差异明显:
- 仅防反向控制原页 →
rel="noopener"足够 - 还希望隐藏来源 URL(比如避免泄露内部路径)→ 加上
noreferrer - 服务端依赖 Referer 做权限校验 → 不能加
noreferrer,否则校验失败
注意:rel="noopener noreferrer" 在 Chrome/Firefox/Safari 中等效于同时禁用 opener 和 referer;但部分旧版 Edge 对 noreferrer 支持不稳定,建议优先测试目标环境。
为什么 rel="noopener" 有时不起作用?
最常见原因是属性拼写或格式错误,浏览器直接忽略整个 rel 值。它不是布尔属性,必须作为完整字符串存在,且值之间用空格分隔。
- ✅ 正确:
<a href="..." target="_blank" rel="noopener noreferrer"></a> - ❌ 错误:
<a href="..." target="_blank" rel="noopener,noreferrer"></a>(逗号分隔会被当做一个无效 token) - ❌ 错误:
<a href="..." target="_blank" rel="noopener"></a>但实际渲染时被 CMS 或 Markdown 解析器过滤掉rel - ❌ 错误:Vue/React 中动态绑定写成
:rel="['noopener']"却未 join 成字符串,导致最终渲染为rel="object Object"
要不要给所有 target="_blank" 都加 rel="noopener"?
要,但得看上下文。内部系统链接(如后台菜单跳转到同域报表页)理论上无风险,但一旦未来域名被劫持或子域被污染,window.opener 就成了突破口。工程上统一加更省心,也避免新人踩坑。
性能影响几乎为零——rel="noopener" 是声明式行为,不触发任何计算或网络请求;但它会改变新页面的 window.opener 值为 null,这点在新页 JS 中若做了 if (window.opener) {...} 判断,需要同步调整逻辑。
真正容易被忽略的是:第三方富文本编辑器(如 TinyMCE、Quill)默认不自动补 rel,CMS 后台插入的外链几乎全是裸 target="_blank",上线前务必检查输出 HTML 或加服务端过滤规则。











