
自2020年起,主流浏览器(Chrome、Firefox、Safari)默认隔离通过 target="_blank" 打开的新窗口,导致 window.opener 为 null;本文详解如何通过 rel="opener" 正确恢复跨窗口通信能力,并覆盖 、、JavaScript 动态表单等全场景实践方案。
自2020年起,主流浏览器(chrome、firefox、safari)默认隔离通过 `target="_blank"` 打开的新窗口,导致 `window.opener` 为 `null`;本文详解如何通过 `rel="opener"` 正确恢复跨窗口通信能力,并覆盖 ``、`
在现代 Web 开发中,当页面通过 target="_blank" 打开新窗口(如弹窗、表单提交跳转)时,出于安全考虑,浏览器会自动将子窗口的 window.opener 属性设为 null,从而切断父页与子页之间的 JavaScript 访问通道。这一变更源于 Chromium 88+、Firefox 79+ 等版本对 rel="noopener" 的默认强化策略——即使未显式声明,target="_blank" 也会隐式附加 rel="noopener",彻底禁用 opener 引用。
要安全且可控地恢复 window.opener 访问权限,核心原则是:显式声明 rel="opener",并确保其作用于正确的 HTML 元素层级。以下是各典型场景的正确实现方式:
✅ 场景一:普通超链接(<a></a> 标签)
只需在 <a></a> 标签中添加 rel="opener"(注意:不可省略 rel="noopener" 的安全对立面,opener 本身不带来风险,但需明确意图):
<a href="https://www.php.cn/link/0649a96e795321782b6c924a9cc5b33d" target="_blank" rel="opener"> Link to child page </a>
⚠️ 注意:
rel="opener"必须与target="_blank"同时存在;若同时写rel="noopener opener",浏览器以noopener为准,opener将被忽略。因此仅保留rel="opener"即可。
✅ 场景二:JavaScript 动态创建表单(如 POST 提交弹窗)
关键点在于:避免使用 target="_blank",改用命名窗口(如 "formresult"),并在 <form></form> 元素上设置 rel="opener":
const form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", "myChildPage.php");
form.setAttribute("target", "formresult"); // 命名窗口,复用或新建
form.setAttribute("rel", "opener"); // ✅ 此处声明生效
// 添加隐藏字段等逻辑...
const input = document.createElement("input");
input.type = "hidden";
input.name = "token";
input.value = "abc123";
form.appendChild(input);
document.body.appendChild(form);
form.submit();
? 命名窗口(如
"formresult")能确保多次提交复用同一窗口,且rel="opener"在<form></form>上声明后,子窗口将正确持有对父窗口window.opener的引用。
✅ 场景三:含 formaction / formtarget 的 <input type="submit">
rel="opener" 不能写在 <input> 标签上(浏览器忽略),而必须提升至其所属 <form></form> 标签:
<!-- ❌ 错误:rel 在 input 上无效 -->
⚠️ 重要注意事项
-
安全性权衡:启用
opener意味着子页面可通过window.opener.location重定向父页(开放型钓鱼风险)。如无需双向通信,应坚持默认rel="noopener"。 -
rel="opener"与rel="noreferrer"互斥:若同时存在,noreferrer优先生效(连Referer头也屏蔽),opener失效。 -
服务端无法绕过:
.htaccess或 HTTP Header(如Referrer-Policy)无法恢复window.opener,此为纯客户端安全策略,必须通过 HTML/JS 显式声明解决。 -
兼容性:
rel="opener"已获 Chrome 88+、Firefox 79+、Edge 88+、Safari 15.4+ 全面支持,旧版浏览器会静默忽略该属性,不影响基础跳转功能。
✅ 验证是否生效
在子页面(childpage.php)中执行以下代码,若输出 true 则配置成功:
console.log(window.opener !== null); // 应为 true console.log(window.opener.location.href); // 可读取父页 URL(需同源)
总结:rel="opener" 是现代浏览器中精准控制 window.opener 行为的标准化方案。开发者应根据交互类型,将该属性置于 <a></a>、<form></form> 或动态创建的表单元素上,杜绝在 <input> 等子元素中错误声明,并始终评估启用 opener 带来的安全边界变化。











