跨域限制由浏览器同源策略强制实施,非HTML5本身提供;iframe无法访问跨域contentWindow、fetch需服务端CORS响应头配合、客户端存储完全隔离,推荐postMessage安全通信。
HTML5 本身不提供
跨域
页面限制能力,真正起作用的是
浏览器
的
(CORS)机制和
、
等 API 的配合使用。直接在 HTML 中写个标签或属性就想“限制跨域”是无效的。
iframe 跨域时无法访问
或
这是最常见的报错场景:父页用
加载后,尝试执行
会抛出
。
这不是 HTML5 的“限制规则”,而是浏览器同源策略(Same-Origin Policy)的强制保护
属性(如
)只影响 iframe 内部权限,不解除跨域 DOM 访问限制
若双方可控,可在子页面顶部加
(仅限同主域不同子域,如
↔
),但现代浏览器已逐步弃用该方式
推荐方案:使用
进行安全通信,父页监听
事件,子页调用
和
跨域请求被拒
前端
JS 发起跨域请求时,即使 URL 正确,也可能收到
或控制台提示
。
关键点不在前端代码,而在服务端响应头是否包含
默认不带凭据(
cookie
s),若需携带,必须显式设置
,且服务端必须返回
(此时
不能为
)
预检请求(OPTIONS)会被自动触发:当请求含自定义 header(如
)或非简单方法(如
),服务端必须正确响应预检,否则请求根本不会发出
、
和
完全隔离
跨域页面之间无法共享任何客户端存储数据——哪怕两个页面只差一个子域名,
和
的
也是完全独立的。
Comet AI 浏览器
下载 Comet AI 浏览器,体验由 Perplexity AI 驱动的革命性上网方式。内置 AI 助手可实时总结网页、跨标签页对比信息、自动执行任务。告别繁琐操作,让 AI 成为你的浏览副驾,大幅提升研究与工作效率。支持 Windows、macOS、Android 和 iOS。
下载
立即学习
“
前端免费学习笔记(深入)
”;
这不是“HTML5 规则限制”,而是浏览器按源(origin)严格划分存储空间
无法通过 JS 绕过;
同理,且受
属性约束
若需跨域同步状态,只能走服务端中转,或用
+ 主域页面做代理(例如让两个子域页面都与
上的中继页通信)
跨域真正的难点从来不在“怎么写 HTML”,而在于理解哪些操作被浏览器拦截、为什么被拦截、以及对应的安全替代路径。很多问题表面是“HTML5 限制”,实际是混淆了规范、API 行为和浏览器实现三者的边界。
Cross-Origin Resource Sharingdocument.domainpostMessagecontentWindowcontentDocumentiframe.contentWindow.document.bodyDOMException: Blocked a frame with origin "http://a.com" from accessing a cross-origin frame.allowallow="clipboard-read"document.domain = "example.com"a.example.comb.example.comwindow.postMessage()messageparent.postMessage(data, "https://parent-domain.com")fetchXMLHttpRequestnet::ERR_FAILEDNo 'Access-Control-Allow-Origin' headerAccess-Control-Allow-Originfetch("https://api.other.com/data")credentials: "include"Access-Control-Allow-Credentials: trueAccess-Control-Allow-Origin*AuthorizationPUTlocalStoragesessionStorageIndexedDBhttps://admin.example.comhttps://api.example.comlocalStoragedocument.cookieSameSitepostMessageexample.comconst iframe = document.getElementById("myIframe");
iframe.contentWindow.postMessage({ type: "GET_USER_INFO" }, "https://child-domain.com");
window.addEventListener("message", (e) => {
if (e.origin !== "https://child-domain.com") return;
if (e.data.type === "USER_INFO_RESPONSE") {
console.log("Received:", e.data.payload);
}
});