rel="noopener" 是浏览器在解析 标签时主动将新页面的 window.opener 设为 null,不可绕过;noreferrer 则额外阻止 Referer 头发送,二者作用不同但常共用。

rel="noopener" 是怎么切断 window.opener 的
它不是靠 JavaScript 拦截或拦截器实现的,而是浏览器在解析 标签时,一旦发现 rel="noopener" 且 target="_blank",就直接把新页面的 window.opener 设为 null。这个动作发生在页面加载初期,不可绕过、不可恢复。
你可以在新标签页的控制台里直接验证:
不加 rel="noopener" → window.opener 是一个有效的 Window 对象;
加了之后 → window.opener 永远是 null,哪怕跨域也一样。
只写 rel="noopener" 还是必须加 noreferrer
rel="noopener" 已经能彻底阻断 window.opener 访问,这是它的核心职责。而 noreferrer 是额外动作:它让浏览器不发送 Referer 请求头,防止目标页面知道你从哪个 URL 过来的。
- 如果你链接的是第三方广告、统计跳转页、或路径含敏感参数(比如
/admin?token=xxx),建议加上noreferrer - 如果只是普通外链(如维基百科、GitHub),
noopener足够防劫持 - 注意:
rel="noreferrer"单独使用时,在部分旧版 Chrome/Safari 中仍会保留window.opener(只是不发 Referer),所以不能替代noopener
target="_blank" 不加 noopener 的典型攻击场景
恶意页面拿到 window.opener 后,最常用也最隐蔽的操作就是静默重定向原页面:
-
window.opener.location.replace('https://fake-login.example.com')—— 用户切回原标签时,看到的就是钓鱼页 -
window.opener.document.title = 'Session expired'—— 伪造提示诱导输入密码 - 配合
document.hidden检测用户是否离开标签,再择机触发操作 - 即使原页面已关闭,只要新页面还开着,opener 引用仍可能有效(取决于浏览器 GC 策略)
兼容性与常见误写
所有现代浏览器(Chrome 49+、Firefox 52+、Safari 10.1+、Edge 79+)都支持 rel="noopener",无需 polyfill。但要注意几个容易踩的坑:
- 写成
rel="noopenner"或rel="nooopener"—— 拼写错误导致完全失效 - 混用空格和引号:
rel= noopener(没引号)、rel="noopener "(末尾空格)—— 部分解析器会忽略 - 动态生成链接时漏掉:比如用 JS 拼
却忘了加rel - Vue/React 中绑定
:rel或rel={...}时,值为空字符串或undefined,结果渲染成rel="",等价于没写
真正起作用的只有完整、正确、带引号的 rel="noopener" 或 rel="noopener noreferrer"。少一个字母,安全链就断了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











