COOP必须通过服务端HTTP响应头设置,meta标签完全无效;其same-origin值切断跨源opener引用但允许同源通信,且须与COEP:require-corp配合才能启用SharedArrayBuffer等高权限API。

COOP 不能靠 <meta> 标签设置,必须由服务端返回 Cross-Origin-Opener-Policy 响应头——这是绝大多数人第一次尝试就失败的根源。
为什么 <meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin"> 完全无效
浏览器规范明确要求该策略只能通过 HTTP 响应头传递,<meta> 写法在 Chrome ≥88、Firefox ≥87、Edge ≥88 中一律被忽略。这不是兼容性问题,是强制设计:它必须在页面加载早期、DOM 构建前就生效,而 <meta> 解析太晚。
常见错误包括:
- 本地开发时用
file://协议打开 HTML —— 此时无响应头机制,COOP 天然不生效 - 用 Express 静态托管但忘了在
res上调用setHeader,或写在了中间件之后(被后续逻辑覆盖) - 部署在 Nginx 时漏掉
add_header,或用了proxy_hide_header把它意外屏蔽了
Cross-Origin-Opener-Policy: same-origin 实际行为到底是什么
它不阻止弹窗打开,只切断 opener 关系。关键表现有:
立即学习“前端免费学习笔记(深入)”;
- 你用
window.open('https://evil.com')打开跨源页面,返回值是null(不是 window 对象) - 对方页面的
window.opener恒为null,无法反向访问你 - 同源弹窗(如
https://a.example.com→https://a.example.com/admin)仍可正常通信 - 协议、端口不同即视为跨源(
http://a.com和https://a.com不互通)
注意:same-origin 和 same-origin-allow-popups 的区别不在“是否允许弹窗”,而在“是否允许同源弹窗保留 opener 引用”——后者对 SSO、支付跳转更友好,但防护强度略低。
单独设 COOP 无法启用 SharedArrayBuffer 或 performance.measureMemory
即使 COOP 生效,self.crossOriginIsolated 仍为 false。因为跨源隔离(crossOriginIsolated)是双条件门控:
- COOP 控制“谁可以 opener 我”
- COEP(
Cross-Origin-Embedder-Policy: require-corp)控制“我能加载谁”
缺一不可。漏掉 COEP,浏览器认为环境仍不安全,高权限 API 直接禁用。验证方式只有一条:在 DevTools Console 中执行 self.crossOriginIsolated,必须返回 true。仅看 Network 面板里两个 header 存在,不代表成功——CDN、Cloudflare、甚至 Nginx 的 gzip_static 都可能 strip 掉响应头。
如何快速确认 COOP 是否真正生效
最直接的方法是检查当前 frame 的 COOP 状态:
- Chrome DevTools → Application → Frames → 查看右侧“COOP”列值,应显示
same-origin - 在页面 JS 中立即执行
console.log(window.opener):若被跨源页面打开,结果必须是null - 用另一个域名页面调用
window.open('your-site.com'),然后在新窗口中运行console.log(opener === null),应为true
最容易被忽略的是:iframe 嵌入场景下,父页和子页的 COOP 是各自独立生效的。如果子 iframe 没配 COOP,即使父页配了,整个上下文组也无法达成完全隔离——self.crossOriginIsolated 仍为 false。


















