检查 JS 是不是可以访问 iframe 的文档

Posted

技术标签:

【中文标题】检查 JS 是不是可以访问 iframe 的文档【英文标题】:Check if JS has access to an iframe's document检查 JS 是否可以访问 iframe 的文档 【发布时间】:2012-08-06 01:24:45 【问题描述】:

是否有任何标准方法可以知道我的脚本是否可以访问iframe 的文档?

我在网上找不到任何东西,所以我想出了这个:

function checkifr() 
    function errHandler() 
        alert('Error. Try again later.');
    
    var ifr = $('#ifr')[0]; //the iframe DOM element

    try 
        var d = ifr.contentWindow || ifr.contentDocument;
        if (!d) 
            errHandler();
            return false;
        

        var b = $('#ifr').contents().find('body');
        //... manipulate iframe content

     catch(e) 
        errHandler();
    

它有效,当我尝试访问iframe 的内容并最终进入catch 块时,Firefox 会引发错误。 Chrome 在控制台中显示Unsafe javascript attempt to access frame 警告,但从未进入catch 块,对于这些尝试,它似乎返回null,因此最初的if (!d) 会处理它。 Opera 和 IE 的行为与 FF 类似。 编辑: 使用上面的代码,现在 Chrome 返回一个“空”窗口对象(没有属性),它不会触发我的 if 块。检查Esailija 的答案,它可以很好地跨浏览器!

这是fiddle

不能测试iframesrcwindow.location

证明背景:这是因为这个功能是我正在开发的一个小图片上传插件的一部分(使用iframe作为目标,因为IE.load 处理程序不会因错误而触发,jQuery 的 .error 和 onerror html 属性对此不起作用。 here 提供了工作脚本的说明,但您可以完全忽略它并简单地回答以下问题。

请注意,上面的块仅用于说明为什么我不能使用iframe.src

我确实认为应该有一种更简单/标准的方法来检查iframe 的“可访问性”,但是除了简单检查iframe.src 和很多情况下不适用。如果我的 hackish try/catch 块被认为是技术上“干净”的解决方案,如果找不到更好的选择,其他人可能会重新使用它。

那么是否有任何标准或更简单的方法或 jQuery 插件来检查我的脚本是否可以访问iframe 的文档而不比较iframesrcwindow.location?如果可能,控制台中没有 try/catch 块和错误/警告。

【问题讨论】:

.documentWindow?哪个浏览器实现了这个? 哦,是的,应该是.contentWindow 很确定我从 SO 中的另一个答案中获得了那部分,但很好的发现! documentWindow 在我测试过的所有浏览器中都返回 undefined 。我会寻找答案来检查这是否是一个错字。 是的,这是我的错字,感谢@ŠimeVidas 和 Esa! 【参考方案1】:

无论访问是否引发异常,这里都有一个可行的想法:

function checkFrameAccess(ifr) 
    try 
        var doc = ifr.contentDocument || ifr.contentWindow.document;
        var origClass = doc.body.className;
        var newClass = origClass += " xxxxx";
        doc.body.className = newClass;
        var valid = doc.body.className == newClass;
        doc.body.className = origClass;
        return(valid);
     catch(e) 
        return(false);
    

如果他们抛出异常,您最终会进入异常处理程序并返回false。如果他们没有抛出异常,那么你测试你是否真的可以修改框架中body标签的className。如果修改有效,那么显然,您可以修改它。如果没有,那么它不会让你访问它。

【讨论】:

-1 没有足够的 jQuery。现在说真的,你的答案是干净和可以理解的。 +1 在 Esailija 之前回答。【参考方案2】:

这是另一种选择,如果不尝试捕获,则无法真正做到。

测试http://jsfiddle.net/LHjwZ/11/

function checkIframe( ifr ) 
    var key = ( +new Date ) + "" + Math.random();

    try 
        var global = ifr.contentWindow;
        global[key] = "asd";
        return global[key] === "asd";
    
    catch( e ) 
        return false;
    

【讨论】:

我明白了,尝试在 iframe 的 contentWindow 中设置一个 var 看起来比我的代码更干净,并且很容易添加到抽象级别。 +1,秒,我阅读其他答案并测试它们。 =] 是的,非常有意义,设置一个以毫秒时间戳命名的窗口属性并与Math.random() 连接似乎有点矫枉过正,但毫无疑问这是代码正确性的标志!

以上是关于检查 JS 是不是可以访问 iframe 的文档的主要内容,如果未能解决你的问题,请参考以下文章

摘抄官方文档: spring boot配置 iframe同源可访问

iframe子页面js调用父页面中的控件报“拒绝访问”是啥原因,怎么解决?先声明不是跨域问题

检查 iframe 内是不是加载了 Vimeo 视频 - jquery

错误:在 iFrame 中访问属性“文档”的权限被拒绝

DW里嵌iframe左右拉条问题

除非我检查元素,否则 C# Selenium 无法访问 iframe 中的元素