获取iframe的location.hash时出现跨域访问阻止DOMException问题求助
location.hash 被拦截的问题 嘿,这问题我太熟了!你碰到的是浏览器核心的同源策略安全限制——浏览器为了防止恶意页面窃取数据,严格禁止不同源的页面互相访问对方的window或DOM属性。错误提示已经说得很清楚:你的主页面(https://localhost:7002)和iframe页面不属于同源,所以直接用iFrame.contentWindow.location.hash读取hash肯定会被拦。
先帮你明确下同源的定义:协议、域名、端口三者必须完全匹配,哪怕都是localhost,端口不一样(比如主页面7002,iframe用3000),或者协议不同(一个https一个http),都会被判定为跨域。
下面给你几个实用的解决方案,按需选:
方案1:让iframe和主页面完全同源
这是最简单的解决办法——先检查iframe的src地址,确保它的协议、域名、端口和主页面(https://localhost:7002)完全一致:
- 如果iframe的src是其他端口、不同协议,或者不同域名,赶紧改成主页面同域的地址;
- 改成同源后,你原来的代码
var urlHash = iFrame.contentWindow.location.hash;就能正常工作了。
方案2:用postMessage实现跨域通信(最常用)
如果iframe的页面没办法改成同源,那postMessage是浏览器官方推荐的跨域通信方案,安全又可靠:
第一步:在iframe页面里发送hash消息
让iframe主动把hash值发给主页面,包括页面加载时和hash变化时:
// iframe页面的代码 // 监听hash变化事件 window.addEventListener('hashchange', () => { // 发送消息给父页面,第二个参数指定主页面域名,更安全 window.parent.postMessage({ type: 'iframe-hash', hash: window.location.hash }, 'https://localhost:7002'); }); // 页面加载完成后主动发送一次初始hash window.onload = () => { window.parent.postMessage({ type: 'iframe-hash', hash: window.location.hash }, 'https://localhost:7002'); };
第二步:在主页面接收消息
在你的abc.js里添加监听,接收iframe发来的hash:
// 主页面abc.js的代码 window.addEventListener('message', (event) => { // 一定要验证消息来源!防止恶意网站发消息过来 if (event.origin !== 'https://你的iframe域名:端口') return; // 判断是我们需要的hash消息 if (event.data.type === 'iframe-hash') { const urlHash = event.data.hash; // 这里就可以处理拿到的hash值了 console.log('拿到iframe的hash:', urlHash); } });
方案3:URL参数传递初始hash(仅适用于静态场景)
如果只需要获取iframe加载时的初始hash,不需要监听变化,可以直接把hash作为参数拼到iframe的src里:
比如原来的iframe src是https://other-site.com/page#section1,改成:
<iframe src="https://other-site.com/page?initial-hash=section1" id="myIframe"></iframe>
然后在主页面直接解析这个URL参数就行,但这种方式没法跟踪hash的后续变化。
最后啰嗦一句:用postMessage的时候,一定要验证event.origin,别图方便用*,指定具体的主页面/iframe域名,能避免很多安全风险。
内容的提问来源于stack exchange,提问作者Lakmal Vithanage




