由于 X-Frame-Options 标头,有什么好的方法可以检测页面何时不会显示在框架中?我知道我可以请求页面服务器端并查找标头,但我很好奇浏览器是否有任何机制来捕获此错误。
8 回答
好的,这个很旧但仍然相关。
事实: 当 iframe 加载被 X-Frame-Options 阻止的 url 时,加载时间非常短。
哈克: 所以如果加载立即发生,我知道这可能是 X-Frame-Options 问题。
免责声明: 这可能是我编写的“最骇人听闻”的代码之一,所以不要期望太多:
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);
免责声明:我在 2012 年写的这个答案(当时的 Chrome 是 ~20 版)已经过时,我将它保留在这里仅用于历史目的。阅读和使用风险自负。
好的,这是一个有点老的问题,但这是我对 Chrome/Chromium 的发现(这不是一个完整的答案)。
检测指向外部地址的框架是否已加载的方法只是尝试访问其 contentWindow 或文档。
这是我使用的代码:
element.innerHTML = '<iframe class="innerPopupIframe" width="100%" height="100%" src="'+href+'"></iframe>';
myframe = $(element).find('iframe');
然后,稍后:
try {
var letstrythis = myframe.contentWindow;
} catch(ex) {
alert('the frame has surely started loading');
}
事实是,如果 X-Frame-Options 禁止访问,那么myFrame.contentWindow
将是可访问的。
这里的问题是我所说的“然后,以后”。我还没有弄清楚要依赖什么,订阅哪个事件来查找何时是执行测试的好时机。
这是基于@Iftach的回答,但不那么老套。
它检查是否iframe.contentWindow.length > 0
表明 iframe 已成功加载。
此外,它还会检查 iframeonload
事件是否在 5 秒内触发并发出警报。这捕获了混合内容的失败加载(尽管以一种骇人听闻的方式)。
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);
现场演示 - https://jsfiddle.net/dvdsmpsn/7qusz4q3/ - 这样您就可以在相关浏览器中对其进行测试。
在撰写本文时,它适用于 Chrome、Safari、Opera、Firefox、Vivaldi 和 Internet Explorer 11 上的当前版本。我还没有在其他浏览器中测试过它。
我唯一能想到的就是为url代理一个AJAX请求,然后查看标头,如果它没有X-Frame-Options,则将其显示在iframe中。远非理想,但总比没有好。
至少在 Chrome 中,您会注意到加载失败,因为 iframe.onload 事件没有触发。您可以将其用作页面可能不允许 iframe 的指示。
在线测试工具可能有用。我使用了 https://www.hurl.it/。您可以清楚地看到响应标头。寻找 X 框架选项。如果值为拒绝 - 它不会显示在 iframe 中。相同的来源 - 仅来自同一域,允许 - 将允许来自特定网站。
如果您想尝试其他工具,您可以简单地在 google 上搜索“http request test online”。
这可以通过
a) 通过 CreateElement 创建一个新的 IFrame
b) 将其显示设置为“无”
c) 通过 src 属性加载 URL
d) 为了等待 iframe 加载,使用 SetTimeOut 方法来延迟函数调用(我已经将调用延迟了 10 秒)
e) 在该函数中,检查 ContentWindow 长度。
f) 如果长度 > 0,则加载 url,否则由于 X-Frame-Options 未加载 URL
下面是示例代码:
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');
}
}
这就是我检查 X-Frames-Options 以满足我的要求之一的方式。在加载 JSP 页面时,您可以使用 AJAX 向特定 URL 发送异步请求,如下所示:
var request = new XMLHttpRequest();
request.open('GET', <insert_URL_here>, false);
request.send(null);
完成后,您可以读取收到的响应标头,如下所示:
var headers = request.getAllResponseHeaders();
然后,您可以对其进行迭代以找出 X-Frames-Options 的值。一旦你有了这个值,你就可以在适当的逻辑中使用它。