Есть ли хороший способ обнаружить, когда страница не будет отображаться в кадре из-за заголовка X-Frame-Options? Я знаю, что могу запросить сервер страниц и искать заголовок, но мне было любопытно, есть ли в браузере какой-либо механизм для обнаружения этой ошибки.
Существует ли клиентский способ обнаружения X-Frame-Options?
Ответ 1
ОК, этот старый, но все же релевантный.
Факт: Когда iframe загружает URL-адрес, который блокируется X-Frame-Options, время загрузки очень короткое.
Hack: Поэтому, если onload происходит сразу, я знаю, что это возможно проблема с параметрами X-Frame.
Отказ от ответственности: Вероятно, это один из самых "тяжелых" кодов, которые я написал, поэтому не ожидайте многого:
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 PROBABLY OK");
}
else {
console.log("It PROBABLY NOT OK");
}
});
}
else {
iframe.onload = function(){
if(timepast) {
console.log("It PROBABLY OK");
}
else {
console.log("It PROBABLY NOT OK");
}
};
}
document.body.appendChild(iframe);
Ответ 2
Отказ от ответственности: этот ответ, который я написал в 2012 году (Chrome был версии ~ 20 в то время) устарел, и я сохраню его здесь только для исторических целей. Прочитайте и используйте на свой страх и риск.
Хорошо, это немного старый вопрос, но вот что я узнал (это не полный ответ) для Chrome/Chromium.
способ обнаружить, был ли загружен фрейм, указывающий на чужой адрес, просто попытаться получить доступ к его содержимому. Окно или документ.
здесь код, который я использовал:
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
будет доступен.
проблема здесь - это то, что я назвал "потом, позже". Я еще не понял, на что полагаться, какое событие, чтобы подписать, чтобы найти, когда самое подходящее время для проведения теста.
Ответ 3
Единственное, о чем я могу думать, это проксировать запрос AJAX для URL-адреса, затем посмотреть заголовки, и если у него нет X-Frame-Options, тогда покажите его в iframe. Далеко от идеала, но лучше, чем ничего.
Ответ 4
По крайней мере, в Chrome вы можете заметить, что загрузка невозможна, поскольку событие iframe.onload не запускается. Вы можете использовать это как индикатор того, что страница может не разрешать iframing.
Ответ 5
Это основано на ответе @Iftach, но немного менее взломан.
Он проверяет, есть ли iframe.contentWindow.length > 0
, который предположил бы, что iframe успешно загружен.
Кроме того, он проверяет, активировано ли событие iframe onload
в течение 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. Я не тестировал их в других браузерах.
Ответ 6
Инструменты онлайн-тестирования могут быть полезны. Я использовал https://www.hurl.it/. вы можете четко видеть заголовок ответа. Найдите вариант X-frame. если значение отрицается - оно не будет отображаться в iframe. то же происхождение - только из того же домена, разрешить использование определенных веб-сайтов.
Если вы хотите попробовать другой инструмент, вы можете просто google для проверки HTTP-запроса онлайн.
Ответ 7
Это может быть достигнуто с помощью
a) Создайте новый IFrame через CreateElement
b) Установите его как "none"
c) Загрузите URL-адрес через атрибут src
d) Чтобы дождаться загрузки iframe, используйте метод SetTimeOut для задержки вызова функции (я задерживал вызов на 10 секунд)
e) В этой функции проверьте длину ContentWindow.
f) если длинa > 0, то URL-адрес загружается, иначе URL-адрес не загружается из-за X-Frame-Options
Ниже приведен пример кода:
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');
}
}
Ответ 8
Вот как я проверил опции 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. Как только у вас есть значение, вы можете использовать его в соответствующей логике.