Как определить, загружается ли веб-страница внутри iframe или непосредственно в окно браузера?

Я пишу приложение на основе iframe facebook. Теперь я хочу использовать ту же html-страницу для отображения обычного веб-сайта, а также страницы canvas в 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")

Теперь в кадре " баз " вы нажимаете ссылку (нет цели, загружается в кадре "баз"), она работает нормально.

Если страница загружается, давайте назовем ее специальной.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.

Это позволяет моему расширению определять в обоих браузерах, есть ли какие-либо iframes присутствующие, и кроме того, в 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 будет передавать кучу данных querystring, включая ключ fb_sig_user, если он вызывается из iframe.

поскольку вам, вероятно, нужно проверить и использовать эти данные в любом случае в вашем приложении, используйте его для определения соответствующего контекста для рендеринга.


лучшие-для-теперь наследие рамка браузера ломать скрипт

другие решения не сработали для меня. Это работает во всех браузерах:

один из способов защиты от 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.

ссылка:https://www.codemagi.com/blog/post/194


Я на самом деле использовал для проверки окна.parent и это сработало для меня, но в последнее время window является циклическим объектом и всегда имеет Родительский ключ, iframe или нет iframe.

поскольку комментарии предполагают жесткое сравнение с window.родитель работает. Не уверен, что это будет работать, если 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"; }

затем он автоматически перенаправляет на главную страницу.