为什么js无法通过contentDocument获取到iframe内容

发布于:2024-04-22 ⋅ 阅读:(163) ⋅ 点赞:(0)

最近在开发一个附件预览的页面,考虑到附件的安全性由后端对内容进行了加密,前端负责在页面引入iframe标签来加载数据,在这个过程中需要实时获取到iframe标签的渲染状态来判断什么时候loading结束:

这里我通过标签的方式来获取到iframe,再通过判断内部body是否有长度来确认loading状态,但是在页面中iframe加载到内容的情况下,无论怎么获取,js拿到的iframe内部都是空的

var iframe = document.getElementsByTagName('iframe')]
var loading = true
 
// 监听iframe加载完成
iframe.onload = function() {
    // 获取iframe的document对象
    var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
 
    // 获取iframe下的body元素
    var iframeBody = iframeDoc.body;
    loading = iframeBody.children?.length < 1
};

观察发现iframe的地址和项目的地址没有满足同源策略

同源策略限制:如果 iframe 加载的内容与主页面不在同一源(即协议、域名和端口相同),那么由于浏览器的同源策略,您将无法访问 iframe 的 contentDocument。在这种情况下,即使 iframe 已经加载完成,您也无法读取其内容。

而对于跨域 iframe,最可靠的方法是让 iframe 的内容主动通知主页面它已经渲染完成。这通常通过 postMessage 方法实现。如果您没有控制权限来修改 iframe 的内容,那么您将无法判断其渲染状态,因为浏览器的同源策略会阻止这种访问。

使用 postMessage 和 message 事件
如果跨域 iframe 的内容允许,您可以使用 window.postMessage 方法来在 iframe 和主页面之间安全地传递消息。iframe 可以在其内容加载和渲染完成后向主页面发送一个消息,主页面可以通过监听 message 事件来接收这个消息。

// 在主页面中监听来自iframe的消息  
window.addEventListener('message', function(event) {  
    if (event.origin !== '期望的iframe源的URL') return; // 安全检查  
    if (event.data === 'iframeRendered') {  
        console.log('iframe已经渲染完成');  
    }  
}, false);

在 iframe 的内容中,当渲染完成时,您可以发送消息:

// 在iframe的内容中发送消息给主页面  
window.parent.postMessage('iframeRendered', '*'); // 注意:'*' 表示接收方可以是任何源,出于安全考虑,应该替换为具体的源URL