Как определить, загружается ли веб-страница внутри iframe или непосредственно в окно браузера?
Я пишу приложение iframe на основе facebook. Теперь я хочу использовать одну и ту же html-страницу для отображения обычного веб-сайта, а также страницы холста в facebook. Я хочу знать, могу ли я определить, была ли страница загружена внутри iframe или непосредственно в браузере?
15 ответов:
браузеры могут блокировать доступ к
window.topиз-за та же политика происхождения. IE ошибки также имеют место. Вот рабочий код:function inIframe () { try { return window.self !== window.top; } catch (e) { return true; } }
topиselfкакwindowобъекты (вместе сparent), так что вы видите, если ваше окно является главным окном.
window.frameElementвозвращает элемент (например,if (window.frameElement) { // in frame } else { // not in frame }Это стандартная
и скорее новыйметод.он точно работает в Chrome и Firefox. Я не могу рекомендовать его как универсальное решение, но здесь следует упомянуть, я думаю.
Роборг прав, но я хотел добавить боковую заметку.
в IE7 / IE8, когда Microsoft добавила вкладки в свой браузер, они сломали одну вещь, которая вызовет хаос с вашим JS, если вы не будете осторожны.
представьте себе этот макет страницы:
MainPage.html IframedPage1.html (named "foo") IframedPage2.html (named "bar") IframedPage3.html (named "baz")Теперь в кадре " baz "вы нажимаете ссылку (нет цели, загружается в кадре" baz") он отлично работает.
Если страница загружается, давайте назовем ее специальной.html, использует JS, чтобы проверить, если "это" имеет Родительский кадр с именем " bar " он вернет true (ожидаемый).
Теперь давайте скажем, что специальный.html-страница при загрузке проверяет Родительский фрейм (для существования и его имени, и если это "бар", он перезагружается в рамке бара. например,
if(window.parent && window.parent.name == 'bar'){ window.parent.location = self.location; }пока все хорошо. Теперь приходит ошибка.
скажем, вместо того, чтобы нажимать на исходную ссылку, как обычно, и загружать специальную.html-страница в рамке "baz", вы щелкнули ее посередине или решили открыть ее в новом Табуляция.
когда эта новая вкладка загружается (без родительских кадров вообще!)IE войдет в бесконечный цикл загрузки страницы! потому что IE "копирует" структуру фрейма в JavaScript таким образом, что новая вкладка имеет родителя, и этот родитель имеет имя "bar".
хорошая новость, что проверка:
if(self == top){ //this returns true! }в этой новой вкладке возвращает true, и таким образом вы можете проверить это нечетное условие.
принятый ответ не работал для меня внутри сценария содержимого расширения Firefox 6.0 (Addon-SDK 1.0): Firefox выполняет сценарий содержимого в каждом: окне верхнего уровня и во всех iframes.
внутри содержимого скрипта я получаю следующие результаты:
(window !== window.top) : false (window.self !== window.top) : trueстранная вещь об этом выходе заключается в том, что он всегда один и тот же независимо от того, выполняется ли код внутри iframe или окна верхнего уровня.
С другой стороны Google Chrome кажется, чтобы выполнить мой скрипт только один раз в окне верхнего уровня, так что выше не будет работать вообще.
что, наконец, сработало для меня в сценарии контента в обоих браузерах:
console.log(window.frames.length + ':' + parent.frames.length);без iframes это печатает
0:0в окне верхнего уровня, содержащий один кадр он печатает1:1, и в единственном iframe документа он печатает0:1.Это позволяет моему расширению определять в обоих браузерах, если есть какие-либо фреймы, и кроме того, в Firefox, если он выполняется внутри одного из фреймов.
Я использую этот:
var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
Я не уверен, как этот пример работает для старых веб-браузеров, но я использую это для IE, Firefox и Chrome без и проблема:
var iFrameDetection = (window === window.parent) ? false : true;
используйте эту функцию javascript в качестве примера того, как это сделать.
function isNoIframeOrIframeInMyHost() { // Validation: it must be loaded as the top page, or if it is loaded in an iframe // then it must be embedded in my own domain. // Info: IF top.location.href is not accessible THEN it is embedded in an iframe // and the domains are different. var myresult = true; try { var tophref = top.location.href; var tophostname = top.location.hostname.toString(); var myhref = location.href; if (tophref === myhref) { myresult = true; } else if (tophostname !== "www.yourdomain.com") { myresult = false; } } catch (error) { // error is a permission error that top.location.href is not accessible // (which means parent domain <> iframe domain)! myresult = false; } return myresult; }
Так как вы спрашиваете в контексте приложения facebook, вы можете рассмотреть возможность обнаружения этого на сервере при первоначальном запросе. Facebook будет передавать кучу данных строки запроса, включая ключ fb_sig_user, если он вызывается из iframe.
поскольку вам, вероятно, нужно проверить и использовать эти данные в любом случае в вашем приложении, используйте его, чтобы определить соответствующий контекст для визуализации.
лучший на данный момент унаследованный браузер Frame Breaking Script
другие решения не работали для меня. Это работает на всех браузерах:
один из способов защиты от clickjacking состоит в том, чтобы включить сценарий "Frame-breaker" на каждой странице, которая не должна быть оформлена. Следующая методология предотвратит создание веб-страницы даже в устаревших браузерах, которые не поддерживают заголовок X-Frame-Options -.
в элементе головки документа добавьте следующее:
<style id="antiClickjack">body{display:none !important;}</style>сначала примените идентификатор к самому элементу стиля:
<script type="text/javascript"> if (self === top) { var antiClickjack = document.getElementById("antiClickjack"); antiClickjack.parentNode.removeChild(antiClickjack); } else { top.location = self.location; } </script>таким образом, все может быть в голове документа, и вам нужен только один метод/taglib в вашем API.
Я на самом деле использовал, чтобы проверить окно.родитель и это сработало для меня, но в последнее время окно является циклическим объектом и всегда имеет Родительский ключ, iframe или нет iframe.
Как комментарии предлагают трудно по сравнению с окном.родитель работает. Не уверен, что это будет работать, если iframe точно такая же веб-страница, как и родительская.
window === window.parent;
Если вы хотите знать, если пользователь получает доступ к вашему приложению с вкладки страницы facebook или холст проверить подписанный запрос. Если вы не получите его, вероятно, пользователь не получает доступ из facebook. Чтобы убедиться, что подтвердите структуру полей signed_request и содержимое полей.
С помощью php-sdk вы можете получить подписанный запрос следующим образом:
$signed_request = $facebook->getSignedRequest();вы можете прочитать больше о подписанном запросе здесь:
https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/
и здесь:
https://developers.facebook.com/docs/reference/login/signed-request/
это закончилось самым простым решением для меня.
<p id="demofsdfsdfs"></p> <script> if(window.self !== window.top) { //run this code if in an iframe document.getElementById("demofsdfsdfs").innerHTML = "in frame"; }else{ //run code if not in an iframe document.getElementById("demofsdfsdfs").innerHTML = "no frame"; } </script>
Это древний кусок кода, который я использовал несколько раз:
if (parent.location.href == self.location.href) { window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468'; }
if (window.frames.length != parent.frames.length) { page loaded in iframe }но только если количество iframes отличается на Вашей странице и странице, которая загружает вас в iframe. Не делайте iframe на своей странице, чтобы иметь 100% гарантию результата этого кода
напишите этот javascript на каждой странице
if (self == top) { window.location = "Home.aspx"; }затем он будет автоматически перенаправляет на домашнюю страницу.
Comments