23

我正在尝试确定是否有任何 iframe 是跨域的。根据这个问题中接受的答案:Detect when iframe is cross-domain, then bust out it says to put the code access contentDocumentof iframe in a try / catchblock. 我在 Chrome 中为跨域 iframe 尝试了这个:

try { 
  document.getElementsByTagName('iframe')[0].contentDocument;
} catch(err){
  console.log("called");
}

它仍然抛出跨域错误并且没有捕获错误。

我还尝试检查父页面 url 的协议 + 主机 + 端口是否在srciframe 中:

function thirdPartyIframe(iframe){
  var url = document.location.protocol + "//" + document.location.hostname + (document.location.port === "" ? "" : ":" + document.location.port);
  var regexp = new RegExp(url.replace(/\//g, "\\/").replace(/\./g, "\\."));
  if (iframe.src === '' || regexp.test(iframe.src)){
    return false;
  } else {
    return true;
  }
}

但这似乎不适用于 Facebook 主页上的第一个 iframesrc等于(它很长):

"http://www.facebook.com/ai.php?aed=AQLlH2cfdnsnLrDUVyqrQPlWpayw9N09Z_iNuhulevbeEfVa4mcVRcT8cjAZOjQb8y1QXab5Ae3aSEJx49U_Qv35rtSp1VC9cY0_CrpOjMDk40hS_Xm57A996YtRVCcWSuRZ_jZERQ_iA_E4621NAbKHT9dsB7uElkRtTvl5K-zPI0jeH-BEnlZIOXbeEdbRC6qCwoToaltolpe-Ot2KWgkfb_vBZYpzUc3jQoEHzLG6tauO9l_hkXpYpHxnt-KYFKIFZ1PgmrHgb0UcGjeKHl7yBR1AbW2n5XgdgaAhFvBjs5GZlKy566nvl8eLRA60orwkwtWYeN8-gKoAmOLm7-6minsWn8lk1h2Qn3p07HCTSnYHfv1aJ6mF5jmuzP0YYe7Ym9ZbmK-tvax4uPAQJ2OdULilKbEh8M-2V9pVY3AC228OPlrRullZuuOg8DI2A8WeMF-fbbOdOFFVCe5Gj1CaZu3LYXiqdG7mUgY6AEpk9ZzGT4fC2K8DInQo1AypCvzG64C_bEWfODeXe0aGbkWwsUUmO7E5HFg0tvZkK5IAR_xxxQ2rlf5jbcEDo_2gdIDdHe1HT75-SJLUsSA0M8EU01oNNPuWwEC2BW6inepc9QPuqeg42tcEbKLU-rIUnXDBLvgutft8azWPPQ6_LafGjCAmC9uTalagoWLLDMpQOThvPg7YeVd7qg_c9Mzn2GAfuswcxDSxyRIZo9MaOhA6mhfXeE1tmjyBBsMxnx08tO21Jsfgch59fmMxpeJzdsNMPK3FAojfglvCQ2Zrt_6ataexUB4xlM7_PhKrfBPtxb5fe2TE9-nlWruNEpoCrzI05yv4Go3CYEWHob06K_9iICfNVTFkSYGTiJnMXCy_fdgfyzUIn5QJIPRo4-Wnyg444zKAO_nyFW59LqbIanHVfFY6ybiA6KeC3meREWzTPSsrU5d_NbYHlJWb8uPNDR04jaH5e2qiYj3Y8qgLQA5m"

我的函数将其归类为不是第三方 iframe,但当我访问它的contentDocument.

我正在寻找一种万无一失的跨浏览器方法来做到这一点。

4

5 回答 5

24

您需要比 try/catch 中的内容多做一点,以处理不同的浏览器并处理浏览器处理跨域访问的不同方式:

function canAccessIFrame(iframe) {
    var html = null;
    try { 
      // deal with older browsers
      var doc = iframe.contentDocument || iframe.contentWindow.document;
      html = doc.body.innerHTML;
    } catch(err){
      // do nothing
    }

    return(html !== null);
}

在您的示例中,这将是:

var accessAllowed = canAccessIFrame(document.getElementsByTagName('iframe')[0]);

工作演示:http: //jsfiddle.net/jfriend00/XsPL6/

在 Chrome 21、Safari 5.1、Firefox 14、IE7、IE8、IE9 中测试。

于 2012-09-12T05:03:11.190 回答
3

适用于现代浏览器的更短、更易读的功能

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

使用 Chrome 79 和 Firefox 52 ESR 进行测试。

说明:您可以检查任何不可跨域访问的 iframe 属性并转换为布尔值。例如:contentDocument/contentWindow.document/location.href/等。

布尔文档:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean

于 2020-01-27T00:01:22.240 回答
0

这是一个较短的版本,将这两种方法与 ES6 结合在一起。请注意,它仅在您的域和 iframed 域具有相同的安全类型时才有效。在此示例中将 google 链接更改为 http,它将不起作用。

let canAccessIFrame = (iframe) => {
       return !!(iframe.contentDocument)
}

let checkIFrameAccess = () => {
        let result = document.getElementById('result')
        let remote = canAccessIFrame(document.getElementById('remote'))
        let local = canAccessIFrame(document.getElementById('local'))
    
    result.innerHTML = `
        Remote iframe access: ${remote}
        <br>Local iframe access:  ${local}
    ` 
}
于 2021-01-29T14:56:43.157 回答
0

我用jquery这样做了。它可能不是 100% 整洁,但对我有用。

$(iframe).load(function (e) {
  try
    {
    // try access to check
    console.log(this.contentWindow.document);
    }
  catch (e)
    {
    console.log(e);
    var messageLC = e.message.toLowerCase();
    if (messageLC.indexOf("x-frame-options") > -1 || messageLC.indexOf('blocked a frame with origin') > -1 || messageLC.indexOf('accessing a cross-origin') > -1)
      {
      // show Error Msg with cause of cross-origin access denied
      }
    else
      {
      // Shoe Error Msg with other cause
      }
    }
});
于 2021-05-07T11:35:03.677 回答
0

在加载之前,我的 IFrame 返回一个空字符串时遇到问题。所以我开始使用以下内容:

function canAccessIFrame(iframe) {
 try { 
   const doc = iframe.contentDocument || iframe.contentWindow.document;
   const html = doc.body.innerHTML;
   return html !== null && html !== ''
 } catch(err){
   return false
 }
}
于 2022-01-18T16:28:20.570 回答