rel="noopener noreferrer"必须与target="_blank"配合使用才生效,单独添加会被浏览器忽略;它仅在创建新浏览上下文时切断opener引用并阻止referer泄露,缺一不可且须小写无空格。

rel="noopener noreferrer"必须和target="_blank"一起写才生效
单独加rel="noopener noreferrer"但没配target="_blank",浏览器直接忽略——它只在创建新浏览上下文时起作用。常见错误是:CMS自动给外链加target="_blank",但服务端模板或富文本导出时漏掉rel,上线后就成了高危漏洞。
必须同时满足两个条件:target值为"_blank"(不能是"blank"、"_new"等非法值),且rel属性显式声明为"noopener noreferrer"。Chrome 88+虽默认隐式启用noopener,但 Safari 和 Firefox 仍需手动写,不能依赖。
-
target="_self"或target="_parent"上硬塞rel="noopener"完全无效 - 写成
rel="no-opener"或rel="NOOPENER"——拼错或大小写错误就彻底失效 -
rel="noreferrer"在旧版 Safari(≤12.0)中不保证window.opener === null,不能替代noopener
怎么批量给已有HTML补上安全rel属性
手动改每个链接容易漏,尤其在评论区、富文本输出、Markdown渲染等动态场景。推荐用脚本一次性扫描并修正,但必须加域名判断逻辑——只对跨域外链加,否则会影响内部跳转。
JavaScript 示例(运行于页面加载后):
document.querySelectorAll('a[href]').forEach(a => {
try {
const url = new URL(a.href, location.href);
if (url.origin !== location.origin && a.target === '_blank') {
a.rel = (a.rel ? a.rel + ' ' : '') + 'noopener noreferrer';
}
} catch (e) {
// href 无法解析(如 mailto:、tel:)则跳过
}
});
- 构建工具(Vite/Webpack)可用 PostHTML 插件,在 HTML 构建阶段自动注入
- Next.js/Nuxt 等 SSR 项目,应封装
<externallink></externallink>组件,强制带rel="noopener noreferrer" - Markdown 渲染器(如 remark)需配置自定义 render hook,拦截
a标签并补rel
富文本编辑器和CMS里最容易漏掉rel的地方
风险不在手写 HTML,而在用户可输入、系统自动生成的环节。CKEditor、TinyMCE 导出的 HTML 默认不加rel;WordPress、Ghost 等 CMS 的文章内嵌外链、评论区自动识别链接,几乎从不自动补全。
典型漏点:
- 用户粘贴
@#@#@#@#@#@#@#@#@#@0,后端没做清洗就直接入库渲染 - 模板引擎(Jinja/Twig)拼接链接:
@#@#@#@#@#@#@#@#@#@1,忘了加rel - 已存在
rel="nofollow"的链接,直接覆盖成rel="noopener",丢失原有 SEO 语义
这类问题 DevTools 不报错,Lighthouse 也未必扫全,得靠正则匹配:/@#@#@#@#@#@#@#@#@#@2模拟点击
location.replace()跳转 + 新窗口监听,或改用postMessage通信替代window.opener
最常被忽略的是:所有window.open(url, "_blank")调用,只要目标不可信,就等于主动交出原页面控制权。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











