只写 target="_blank" 危险,因新页可通过 window.opener 劫持或卡死原页面;必须加 rel="noopener" 切断 opener 引用,推荐追加 noreferrer 防 referer 泄露,动态生成时需显式设置,旧浏览器需用 window.open(..., '_blank', 'noopener') 兜底。

直接写 target="_blank" 会打开新标签页,但不加 rel="noopener" 就等于给对方页面一把原页面的钥匙——它能跳转、篡改 DOM、甚至卡死你的页面。
为什么只写 target="_blank" 是危险操作
新页面拿到 window.opener 后,同源下可直接执行 window.opener.location = 'https://evil.com' 劫持原页;跨源时虽受限制,但现代浏览器仍允许部分读取和阻塞主线程。常见现象包括:
- 点开链接后切回原页,发现地址已悄悄跳转
- 原页面明显卡顿,尤其新页运行 heavy JS 时
- 控制台报
Blocked a frame with origin ... from accessing a cross-origin frame(其实是浏览器在拦截攻击)
rel 属性必须怎么写才安全
rel="noopener" 是底线,rel="noreferrer" 是额外防护,但二者不能互相替代:
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
-
rel="noopener":切断window.opener引用,防劫持+性能拖累(必须加) -
rel="noreferrer":额外移除 Referer 头,防来源泄露(可选,但推荐) - 别写成
rel="noopener noreferrer"——noopener已隐含对 opener 的隔离,noreferrer在这里只是补 Referer 控制,不是安全冗余 - 拼错成
ref="noopener"(少一个l)或漏掉引号都会失效
动态生成链接时最容易漏 rel
Vue/React 模板里只条件绑定 target、CMS 富文本过滤 rel、JS 拼 innerHTML,都容易裸奔:
- 用 DOM API 创建时,必须显式赋值:
link.rel = 'noopener'(或'noopener noreferrer') - 遍历外部链接批量补时,用
document.querySelectorAll('a[href^="http"]:not([href*="yoursite.com"])')避免误伤内链 - 检查是否已有
rel,避免重复添加(某些框架会自动加) - 服务端模板(如 Jinja、EJS)中硬编码
target="_blank"的地方,必须同步补rel="noopener"
兼容旧浏览器和 WebView 的兜底方案
IE11 及以下完全忽略 rel="noopener",Safari ≤12.0 对 noreferrer 的 opener 隔离支持不完整:
- 若必须支持 IE,改用
window.open(url, '_blank', 'noopener')(注意:这里的noopener是window.open()的 features 字符串参数,不是 HTML 属性) - 该方式需用户交互触发(如 click 事件内调用),否则被弹窗拦截
- 别用
onclick="window.open()"替代原生<a></a>标签——会丢失右键菜单、SEO 和可访问性支持
真正难的不是写对那两个属性,而是每次加 target="_blank" 时,本能地多敲一遍 rel="noopener"。漏一次,风险就存在一次。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










