简体   繁体   English

是否有客户端方式来检测X-Frame-Options?

[英]Is there a client-side way to detect X-Frame-Options?

Is there any good way to detect when a page isn't going to display in a frame because of the X-Frame-Options header? 有没有什么好方法可以检测由于X-Frame-Options标题页面何时不会显示在页面中? I know I can request the page serverside and look for the header, but I was curious if the browser has any mechanism for catching this error. 我知道我可以请求页面服务器端并查找标题,但我很好奇浏览器是否有任何捕获此错误的机制。

OK, this one is old but still relevant. 好吧,这个很旧但仍然相关。

Fact: When an iframe loads a url which is blocked by a X-Frame-Options the loading time is very short. 事实:当iframe加载被X-Frame-Options阻止的URL时,加载时间非常短。

Hack: So if the onload occurs immediately I know it's probably a X-Frame-Options issue. Hack:所以如果onload立即发生,我知道它可能是一个X-Frame-Options问题。

Disclaimer: This is probably one of the 'hackiest' code I've written, so don't expect much: 免责声明:这可能是我编写的“最骇客”的代码之一,所以不要期望太多:

var timepast=false; 
var iframe = document.createElement("iframe");

iframe.style.cssText = "position:fixed; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;";
iframe.src = "http://pix.do"; // This will work
//iframe.src = "http://google.com"; // This won't work
iframe.id = "theFrame";

// If more then 500ms past that means a page is loading inside the iFrame
setTimeout(function() {
    timepast = true;
},500);

if (iframe.attachEvent){
    iframe.attachEvent("onload", function(){
    if(timepast) {
            console.log("It's PROBABLY OK");
        }
        else {
            console.log("It's PROBABLY NOT OK");
        }
    });
} 
else {
    iframe.onload = function(){
        if(timepast) {
            console.log("It's PROBABLY OK");
        }
        else {
            console.log("It's PROBABLY NOT OK");
        }
    };
}
document.body.appendChild(iframe);

Disclaimer: this answer I wrote in 2012(Chrome was version ~20 at that time) is outdated and I'll keep it here for historical purposes only. 免责声明:我在2012年写的这个答案(Chrome当时的版本是20版)已经过时了,我会将它保留在这里仅用于历史目的。 Read and use at your own risk. 阅读和使用需要您自担风险。


Ok, this is a bit old question, but here's what I found out (it's not a complete answer) for Chrome/Chromium. 好的,这是一个有点老问题,但这是我发现的(这不是一个完整的答案)Chrome / Chromium。

the way do detect if a frame pointing to a foreign address has loaded is simply to try to access its contentWindow or document. 检测指向外部地址的帧是否已加载的方法只是尝试访问其contentWindow或文档。

here's the code I used: 这是我使用的代码:

element.innerHTML = '<iframe class="innerPopupIframe" width="100%" height="100%" src="'+href+'"></iframe>';
myframe = $(element).find('iframe');

then, later: 然后,后来:

try {
    var letstrythis = myframe.contentWindow;
} catch(ex) {
    alert('the frame has surely started loading');
}

the fact is, if the X-Frame-Options forbid access, then myFrame.contentWindow will be accessible. 事实是,如果X-Frame-Options禁止访问,那么myFrame.contentWindow将是可访问的。

the problem here is what I called "then, later". 这里的问题是我所谓的“当时,后来”。 I haven't figured out yet on what to rely, which event to subsribe to find when is the good time to perform the test. 我还没有想出要依赖什么,哪个事件可以用来查找何时是进行测试的好时机。

This is based on @Iftach 's answer, but is a slightly less hacky. 这是基于@Iftach的答案,但是稍微不那么苛刻。

It checks to see if iframe.contentWindow.length > 0 which would suggest that the iframe has successfully loaded. 它检查iframe.contentWindow.length > 0是否表明iframe已成功加载。

Additionally, it checks to see if the iframe onload event has fired within 5s and alerts that too. 此外,它会检查iframe onload事件是否在5秒内触发并发出警报。 This catches failed loading of mixed content (in an albeit hacky manner). 这可以捕获混合内容的加载失败(尽管是hacky方式)。

var iframeLoaded = false;
var iframe = document.createElement('iframe');

// ***** SWAP THE `iframe.src` VALUE BELOW FOR DIFFERENT RESULTS ***** //
// iframe.src = "https://davidsimpson.me"; // This will work
iframe.src = "https://google.com"; // This won't work

iframe.id = 'theFrame';
iframe.style.cssText = 'position:fixed; top:40px; left:10px; bottom:10px;'
 + 'right:10px; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;';

var iframeOnloadEvent = function () {
    iframeLoaded = true;
  var consoleDiv = document.getElementById('console');
    if (iframe.contentWindow.length > 0) {
    consoleDiv.innerHTML = '✔ Content window loaded: ' + iframe.src;
    consoleDiv.style.cssText = 'color: green;'
    } else {
    consoleDiv.innerHTML = '✘ Content window failed to load: ' + iframe.src;
    consoleDiv.style.cssText = 'color: red;'
    }
} 

if (iframe.attachEvent){
    iframe.attachEvent('onload', iframeOnloadEvent);
} else {
    iframe.onload = iframeOnloadEvent;
}
document.body.appendChild(iframe);

// iframe.onload event doesn't trigger in firefox if loading mixed content (http iframe in https parent) and it is blocked.
setTimeout(function () {
    if (iframeLoaded === false) {
        console.error('%c✘ iframe failed to load within 5s', 'font-size: 2em;');
    consoleDiv.innerHTML = '✘ iframe failed to load within 5s: ' + iframe.src;
    consoleDiv.style.cssText = 'color: red;'    
  }
}, 5000);

Live demo here - https://jsfiddle.net/dvdsmpsn/7qusz4q3/ - so you can test it in the relevant browsers. 现场演示 - https://jsfiddle.net/dvdsmpsn/7qusz4q3/ - 所以你可以在相关的浏览器中测试它。

At time of writing, it works on the current version on Chrome, Safari, Opera, Firefox, Vivaldi & Internet Explorer 11. I've not tested it in other browsers. 在撰写本文时,它适用于Chrome,Safari,Opera,Firefox,Vivaldi和Internet Explorer 11上的当前版本。我没有在其他浏览器中测试它。

Online test tools might be useful. 在线测试工具可能很有用。 I used https://www.hurl.it/ . 我使用https://www.hurl.it/ you can clearly see the response header. 你可以清楚地看到响应头。 Look for X-frame-option. 寻找X-frame-option。 if value is deny - It will not display in iframe. 如果值为拒绝 - 它将不会显示在iframe中。 same origin- only from the same domain, allow- will allow from specific websites. 同一来源 - 仅来自同一域,允许 - 允许来自特定网站。

If you want to try another tool, you can simply google for 'http request test online'. 如果你想尝试其他工具,你可以简单地谷歌搜索'http request test online'。

The only thing I can think of is to proxy an AJAX request for the url, then look at the headers, and if it doesn't have X-Frame-Options, then show it in the iframe. 我唯一能想到的是为url代理一个AJAX请求,然后查看标题,如果它没有X-Frame-Options,那么在iframe中显示它。 Far from ideal, but better than nothing. 远非理想,但总比没有好。

At least in Chrome, you can notice the failure to load because the iframe.onload event doesn't trigger. 至少在Chrome中,您可以注意到加载失败,因为iframe.onload事件未触发。 You could use that as an indicator that the page might not allow iframing. 您可以将其用作指示页面可能不允许iframing。

This can be achieved through 这可以通过实现

a) Create a new IFrame through CreateElement a)通过CreateElement创建一个新的IFrame

b) Set its display as 'none' b)将其显示设置为“无”

c) Load the URL through the src attribute c)通过src属性加载URL

d) In order to wait for the iframe to load, use the SetTimeOut method to delay a function call (i had delayed the call by 10 sec) d)为了等待iframe加载,使用SetTimeOut方法延迟函数调用(我将调用延迟了10秒)

e) In that function, check for the ContentWindow length. e)在该函数中,检查ContentWindow长度。

f) if the length > 0, then the url is loaded else URL is not loaded due to X-Frame-Options f)如果长度> 0,则加载url,否则由于X-Frame-Options而未加载URL

Below is the sample code: 以下是示例代码:

function isLoaded(val) {
var elemId = document.getElementById('ctlx');
if (elemId != null)
    document.body.removeChild(elemId);


var obj= document.createElement('iframe');

obj.setAttribute("id", "ctlx");

obj.src = val;
obj.style.display = 'none';

document.body.appendChild(obj);

setTimeout(canLoad, 10000);  

}

function canLoad() {
//var elemId = document.getElementById('ctl100');
var elemId = document.getElementById('ctlx');
if (elemId.contentWindow.length > 0) {
    elemId.style.display = 'inline';

}

else {
    elemId.src = '';
    elemId.style.display = 'none';
    alert('not supported');
}
}

This is how I had checked for X-Frames-Options for one of my requirements. 这就是我根据我的要求检查X-Frames-Options的方法。 On load of a JSP page, you can use AJAX to send an asynchronous request to the specific URL as follows: 在加载JSP页面时,您可以使用AJAX向特定URL发送异步请求,如下所示:

var request = new XMLHttpRequest();
request.open('GET', <insert_URL_here>, false);
request.send(null);

After this is done, you can read the response headers received as follows: 完成此操作后,您可以按如下方式阅读收到的响应标头:

var headers = request.getAllResponseHeaders();

You can then iterate over this to find out the value of the X-Frames-Options. 然后,您可以对此进行迭代,以找出X-Frames-Options的值。 Once you have the value, you can use it in an appropriate logic. 获得该值后,您可以在适当的逻辑中使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM