检查JS是否可以访问iframe文档

问题描述 投票:14回答:3

是否有任何标准方法可以知道我的脚本是否可以访问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的内容时,Firefox抛出错误,并最终出现在catch块中。 Chrome在控制台中显示Unsafe JavaScript attempt to access frame警告,但从不进入catch块,对于这些尝试,Chrome似乎返回null,因此初始if (!d)负责处理。 Opera和IE的行为类似于FF。 编辑:使用上面的代码,Chrome现在返回一个“空” Window对象(无属性),该对象不会触发我的if块。查看Esailija的答案,跨浏览器效果很好!

这里是fiddle

无法iframesrcwindow.location进行测试。

司法背景:这是因为此功能是我正在开发的小型图像上传插件的一部分(由于IE <9不支持XHR2,因此使用iframe作为目标),并且目标是主要验证连接错误/超时/等。这些错误的默认浏览器页面受同样的来源政策约束,因此,此问题旨在解决。我不想发送ajax调用来检查页面是否可用,因为我想验证提交请求本身。 jQuery的.load处理程序不会因错误而触发,jQuery的.erroronerror HTML属性对此无效。 here提供了工作脚本的插图,但您可以完全忽略它,而只需回答以下问题。

注意,以上代码仅用于说明为什么我不能使用iframe.src

我确实认为应该有一种更简单/标准的方法来检查iframe的“可访问性”,但是我无法在网络上找到任何东西,除了半解决方案,它只能检查iframe.src而不会不适用于许多情况。如果我的try / catch代码块被认为是一种技术上“干净”的解决方案,那么如果找不到更好的选择,则其他人可以重新使用它。

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

javascript jquery iframe same-origin-policy
3个回答
12
投票

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

测试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;
    }
}

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。如果修改有效,那么显然可以进行修改。如果没有,那么它将不允许您访问它。


0
投票

对于现代浏览器而言,更短,更易读的功能

function canAccessIframe(iframe) {
  try {
    return Boolean(iframe.contentDocument);
  }
  catch(e){
    return false;
  }
}

已通过Chrome 79和Firefox 52 ESR测试。

ps.s。您可以检查跨域不可访问的所有iframe属性,并将其转换为布尔值。例如:contentDocument / contentWindow.document / location.href等。

© www.soinside.com 2019 - 2024. All rights reserved.