只写 target="_blank" 会出安全问题,新页面可通过 window.opener 劫持原页面跳转、篡改 DOM 或触发卡顿;必须搭配 rel="noopener" 切断 opener 引用,消除反向标签劫持风险。

只写 target="_blank" 会出安全问题
单独加 target="_blank" 看似能新开标签页,但新页面可通过 window.opener 直接操控原页面:比如执行 window.opener.location = 'https://evil.com' 劫持跳转,或读取历史、触发卡顿。现代浏览器虽对跨源 window.opener 默认设为 null,但同源下仍完全可读写,旧版 Safari/IE 更无防护。
常见错误现象包括:点开外部链接后原页面变卡、返回时发现地址被悄悄改掉、控制台出现 Blocked a frame with origin ... from accessing a cross-origin frame 报错(其实是防御性拦截,说明风险已存在)。
-
rel="noopener"是必须项,它切断window.opener引用,消除劫持与性能隐患 -
rel="noreferrer"会额外移除Referer头,适合不想泄露来源的场景,但可能影响统计或权限校验 - 不要写成
rel="noopener noreferrer"——noopener已隐含noreferrer的 opener 行为,二者并列冗余(尽管浏览器兼容) - 即使链接指向同域页面(如内部文档),也要加
rel="noopener",因为同源下window.opener完全可控
target="_blank" 不等于“强制新开窗口”
规范只要求“新开浏览上下文”,具体是标签页还是窗口,由用户浏览器设置决定,开发者无法强制:
- Safari iOS:固定在新标签页打开,不可配置
- Safari macOS:受系统「在新窗口中打开链接」选项影响
- Firefox:通过
browser.link.open_newwindow配置项控制(值为 1/2/3) - Chrome:默认倾向新标签页,但用户可改设置
想真正控制尺寸、位置或是否可调整,必须用 window.open(),但会被多数浏览器弹窗拦截,需用户交互触发(如点击事件内调用)。
立即学习“前端免费学习笔记(深入)”;
动态渲染时容易漏掉 rel 属性
在 Vue/React 等框架中,仅条件绑定 target 而忽略 rel 是高频疏漏:
- 写成
:target="isExternal ? '_blank' : '_self'"却没同步写:rel="isExternal ? 'noopener' : ''"→ 外部链接裸奔 - 服务端渲染或 CMS 输出静态 HTML 时,若模板未内置
rel="noopener",人工补写易遗漏 - 用 JS 批量处理外部链接时,只遍历
href是否含http,却忘了给所有匹配元素统一加rel="noopener"
建议在构建时用 ESLint 插件(如 eslint-plugin-jsx-a11y)或 Lighthouse 审计自动拦截缺失 rel 的 target="_blank" 标签——它在审计中直接标为「严重」问题。
target 的其他合法值别乱用
target 不只有 _blank,选错会导致意外覆盖或打不开:
-
target="_self":显式写出可提高可读性,尤其在嵌套 iframe 场景中避免歧义 -
target="_parent"和target="_top"主要用于 iframe 嵌套结构,非框架页中效果等同_self -
target="my-frame":需页面中存在<iframe name="my-frame">,否则退化为_blank(但行为不可控) -
target="_BLANK"或target=" blank":大小写敏感或带空格 → 浏览器当作自定义命名窗口处理,可能复用已有标签页,导致内容被覆盖
真正安全且通用的新标签页写法就这一行:<a href="https://example.com" target="_blank" rel="noopener">Link</a>。别省略 rel,哪怕只是个纯静态链接——这个细节上线后就是长期攻击面。



















