检测iframe是否为跨域的万无一失的方法

use*_*569 18 html javascript security iframe cross-domain

我正在尝试确定是否有任何iframe是跨域的.根据此问题中接受的答案:检测iframe何时是跨域的,然后将删除,然后将代码访问contentDocumentiframe放入try / catch块中.我在Chrome中尝试使用跨域iframe:

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

它仍然会抛出跨域错误,并且不会捕获错误.

我还试图检查父页面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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

"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"
Run Code Online (Sandbox Code Playgroud)

我的功能将其归类为非第三方iframe,但Chrome访问时仍然会引发跨域错误contentDocument.

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

jfr*_*d00 18

你需要做一些比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);
}
Run Code Online (Sandbox Code Playgroud)

在您的示例中,这将是:

var accessAllowed = canAccessIFrame(document.getElementsByTagName('iframe')[0]);
Run Code Online (Sandbox Code Playgroud)

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

在Chrome 21,Safari 5.1,Firefox 14,IE7,IE8,IE9中测试过.

  • Chrome会抛出并记录自己的错误,这个片段的try..catch似乎无法捕获.我会说这很重要.当我安全地测试iframe访问并解决它时,我不希望垃圾邮件控制台出错. (3认同)
  • 如果父级是跨域或同一域,那么从嵌入内容测试来看,另一个方向的安全等效是什么?如果有人感兴趣,我已经将此作为一个单独的问题提出:[检测此页面是否在跨域 iframe 内的万无一失的方法](http://stackoverflow.com/questions/21751377/foolproof-way-to-detect -如果此页面位于跨域 iframe 内) (2认同)

eli*_*z82 7

适用于现代浏览器的更短、更易读的函数

function canAccessIframe(iframe) {
  try {
    return Boolean(iframe.contentDocument);
  }
  catch(e){
    return false;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • @Hexodus 你也可以删除括号 (2认同)