Определение того, является ли документ верхним уровнем или из iframe [duplicate]

Это один лайнер с lodash.

const deep = { l1: { l2: { l3: "Hello" } } };
const prop = "l1.l2.l3";
const val = _.reduce(prop.split('.'), function(result, value) { return result ? result[value] : undefined; }, deep);
// val === "Hello"

Или даже лучше ...

const val = _.get(deep, prop);

Или версия ES6 с уменьшением ...

const val = prop.split('.').reduce((r, val) => { return r ? r[val] : undefined; }, deep);

Plunkr

463
задан akshat 28 November 2008 в 16:45
поделиться

15 ответов

Браузеры могут заблокировать доступ к window.top из-за политики того же происхождения . Ошибки IE также имеют место. Вот рабочий код:

function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

top и self - оба объекта window (вместе с parent), поэтому вы видите, что ваше окно является верхним окном.

868
ответ дан James Gentes 28 August 2018 в 01:33
поделиться
  • 1
    Кажется, это прекрасно работает в Firefox. Работает ли он и в других браузерах? – akshat 28 November 2008 в 16:51
  • 2
    Имея страницу с iframe в iframe, чтобы проверить из моего дочернего iframe, если мой родительский iframe был включен в страницу, я использовал if (parent === top) – sglessard 27 March 2012 в 15:31
  • 3
    @sglessard Если дочерняя страница и родительские ролики из разных доменов, то Firefox будет жаловаться на политику одинакового происхождения (www.w3.org/Security/wiki/Same_Origin_Policy), и код не будет работать – Gaurang Jadia 31 July 2012 в 23:10
  • 4
    Это работает в IE 11, 10 и 9 для меня. Также он работает в FF и Opera, а также, конечно же, Chrome. У меня нет проблем с этим. – jeremysawesome 22 August 2013 в 17:40
  • 5
    Хороший человек, через 8 лет ваше решение поможет мне :) – Lucas Costa 21 October 2016 в 03:05

Лучше всего для устаревших браузеров Frame Breaking Script

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

. Один из способов защитить от clickjacking - включить скрипт «frame-breaker» на каждой странице, который не должен быть обрамлен. Следующая методология предотвратит создание веб-страницы даже в старых браузерах, которые не поддерживают X-Frame-Options-Header.

В элементе HEAD документа добавьте следующее:

<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>

Таким образом, все может быть в документе HEAD, и вам нужен только один метод / taglib в вашем API.

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

0
ответ дан Albert Olivé 28 August 2018 в 01:33
поделиться

Это закончилось как самое простое решение для меня.

    <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>
0
ответ дан Alex Roseland 28 August 2018 в 01:33
поделиться

Напишите этот javascript на каждой странице

if (self == top)
  { window.location = "Home.aspx"; }

Затем он автоматически перенаправляется на домашнюю страницу.

-4
ответ дан Alexis Wilke 28 August 2018 в 01:33
поделиться
  • 1
    Ваше перенаправление будет работать, если вы не являетесь фреймом. Поэтому я не смог бы перемещаться по вашему сайту. Во-вторых, существуют методы предотвращения перенаправления с родительской страницы. – Marius Balčytis 14 May 2013 в 01:35

Я не уверен, как этот пример работает для старых веб-браузеров, но я использую это для IE, Firefox и Chrome без проблем:

var iFrameDetection = (window === window.parent) ? false : true;
3
ответ дан bfontaine 28 August 2018 в 01:33
поделиться

Я использую это:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
5
ответ дан Chuck Norris 28 August 2018 в 01:33
поделиться
  • 1
    Зачем вы это делаете: .indexOf("HTMLIFrameElement")? – Luke 14 August 2013 в 09:46
  • 2
    .indexOf ('foobarbaz') & gt; -1 является способом проверки соответствия «подстроки» и т. Д. (т. е. можно ли «foobarbaz» найти где-нибудь внутри строки?), но без использования регулярных выражений. Это логически эквивалентно .match (/ foobarbaz /). Он (используется для :-) работы в более широком диапазоне браузеров и по-прежнему может использоваться как по привычке, так и из-за опасений относительно эффективности механизмов регулярной экспрессии. – Chuck Kollars 31 August 2013 в 01:01

Это древний фрагмент кода, который я использовал несколько раз:

if (parent.location.href == self.location.href) {
    window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}
-1
ответ дан Error601 28 August 2018 в 01:33
поделиться
  • 1
    Из-за чтения XSS расположение родителя не допускается. – Eneko Alonso 27 September 2012 в 22:28
  • 2
    Чтобы добавить к Eneko Alonso: это работает (parent.location == self.location) – piotr_cz 20 August 2013 в 13:21
  • 3
    @piotr_cz, он работает только в том случае, если политика того же происхождения позволяет получить доступ к parent.location. В противном случае исключается исключение – Dan 13 January 2014 в 12:50

Поскольку вы спрашиваете в контексте приложения facebook, возможно, вам стоит подумать об обнаружении этого на сервере при первоначальном запросе. Facebook будет передавать кучу данных запроса, включая ключ fb_sig_user, если он вызывается из iframe.

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

1
ответ дан HectorMac 28 August 2018 в 01:33
поделиться

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

Поскольку комментарии показывают, что трудно сравнивать с window.parent работает. Не уверен, что это будет работать, если iframe является точно такой же веб-страницей, что и родительский.

window === window.parent;
1
ответ дан Jabran Saeed 28 August 2018 в 01:33
поделиться
  • 1
    Это не работает в opera mini 11 – Serg 29 October 2015 в 14:36
  • 2
    в хром в контексте главного окна window.parent === window истинно. Поэтому ваш ответ неверен. И этот сопоставление можно было использовать для проверки (по крайней мере, в хроме, не проверял его в других браузерах). – MarkosyanArtur 8 February 2017 в 12:29
  • 3
    НЕ РАБОТАЕТ в контексте iFrame, но `if (window === window.parent) {` does. Я не отмечаю тебя, потому что не знаю, почему он не работает. – www-0av-Com 10 April 2018 в 13:24

Если вы хотите узнать, имеет ли пользователь доступ к вашему приложению с вкладки страницы facebook или проверки холста для подписанного запроса. Если вы этого не сделаете, возможно, пользователь не обращается к Facebook. Чтобы убедиться в подтверждении структуры и содержимого полей signed_request.

С помощью php-sdk вы можете получить подписанный запрос следующим образом:

$signed_request = $facebook->getSignedRequest();

Вы можете узнать больше о Signed Request здесь:

https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/

и здесь:

https://developers.facebook.com/docs/reference/login/signed-request/

0
ответ дан Joao Belchior 28 August 2018 в 01:33
поделиться

window.frameElement Возвращает элемент (например, & lt; iframe & gt; или & lt; object & gt;), в который встроено окно, или значение null, если окно находится на верхнем уровне. Таким образом, идентификационный код выглядит как

if (window.frameElement) {
  // in frame
}
else {
  // not in frame
}

Это стандартный и довольно новый метод. Он точно работает в Chrome и Firefox. Я не могу рекомендовать его как универсальное решение, но здесь я должен упомянуть.

66
ответ дан Konstantin Smolyanin 28 August 2018 в 01:33
поделиться
  • 1
    Заметка, пытающаяся прочитать frameElement, выдает исключение SecurityError в iframe с перекрестным началом, согласно W3C ( WHATWG говорит, что он должен возвращать null вместо этого). Поэтому вы можете обернуть его внутри оператора try...catch. – Oriol 31 March 2016 в 14:20
  • 2
    This is rather new [...] method & lt; - через вашу ссылку, это говорит IE5.5. Я тестировал IE9 - кажется, работает нормально. – Neolisk 21 February 2017 в 16:31
  • 3
    это действительно не работает – user151496 3 April 2017 в 12:13
  • 4
    получение null внутри и вне iframe – OlehZiniak 23 August 2017 в 10:22
  • 5
    Описание в MDN говорит, что «если документ, в который он встроен, имеет другое происхождение (например, расположенное из другого домена), это значение« null ». – xeophin 8 January 2018 в 11:40

Принятый ответ не работал для меня внутри скрипта содержимого Firefox 6.0 Extension (Addon-SDK 1.0): Firefox выполняет сценарий содержимого в каждом: окно верхнего уровня и во всех iframe.

Внутри скрипта содержимого я получаю следующие результаты:

 (window !== window.top) : false 
 (window.self !== window.top) : true

Странная вещь в этом выходе заключается в том, что она всегда одинакова независимо от того, выполняется ли код внутри iframe или Окно верхнего уровня.

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

Что, наконец, сработало для меня в сценарии содержимого в обоих браузерах, это:

 console.log(window.frames.length + ':' + parent.frames.length);

Без iframe это печатает 0:0, в окне верхнего уровня, содержащем один кадр, он печатает 1:1, а в единственный iframe документа, который он печатает 0:1.

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

16
ответ дан magnoz 28 August 2018 в 01:33
поделиться
  • 1
    Попробуйте document.defaultView.self === document.defaultView.top или window !== window.top. В сценарии содержимого добавочного SDK Firefox глобальный объект self - это объект, используемый для связи с основным скриптом. – Rob W 1 October 2013 в 22:39

Используйте эту функцию 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;
}
2
ответ дан Rolf 28 August 2018 в 01:33
поделиться

RoBorg прав, но я хотел добавить примечание к стороне.

В IE7 / IE8, когда Microsoft добавила вкладки в свой браузер, они сломали одну вещь, которая приведет к хаосу с вашим JS, если вы не будете осторожны .

Представьте себе этот макет страницы:

MainPage.html
  IframedPage1.html   (named "foo")
  IframedPage2.html   (named "bar")
    IframedPage3.html (named "baz")

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

Если загружаемая страница позволяет вызвать ее special.html, она использует JS для проверки, имеет ли «родительский кадр» родительский фрейм с именем «bar», он вернет true (ожидается).

Теперь скажем, что страница special.html при загрузке проверяет родительский фрейм (для существования и его имени, а если это «бар», он перезагружается в рамке бара, например

if(window.parent && window.parent.name == 'bar'){
  window.parent.location = self.location;
}
[g8 []

Скажем, вместо того, чтобы нажимать на исходную ссылку, как обычно, и загружать страницу special.html в рамке «baz», щелкнул его или решил открыть его в новой вкладке.

Когда эта новая вкладка загружает ( без родительских кадров вообще! ) IE войдет в бесконечный цикл загрузки страницы! потому что IE «копирует» структуру кадра в JavaScript, так что новая вкладка имеет родительский элемент, а у этого родителя есть имя «bar».

Хорошей новостью является проверка:

if(self == top){
  //this returns true!
}

в этой новой вкладке вернет true, и вы можете проверить это нечетное состояние.

25
ответ дан scunliffe 28 August 2018 в 01:33
поделиться
  • 1
    Была ли исправлена ​​ошибка? Я не могу воспроизвести его в IE8. Я всегда получаю правильный window.parent. – user123444555621 10 September 2012 в 08:22
  • 2
    Не уверен - я запустил свой тестовый пакет против IE9 и ниже и разместил обновление. – scunliffe 10 September 2012 в 21:36
  • 3
    @scunliffe - Любое обновление? – Nick 27 August 2013 в 21:58
if (window.frames.length != parent.frames.length) { page loaded in iframe }

Но только если число ваших iframe отличается на вашей странице и странице, которые загружают вас в iframe. Не делайте iframe на своей странице, чтобы получить 100% гарантию результата этого кода

-3
ответ дан Vova Popov 28 August 2018 в 01:33
поделиться
  • 1
    Не очень изящное решение для определения того, находится ли окно внутри iframe или нет, и нет никакой гарантии, что вы также сможете читать из parent.frames. – Percy 22 September 2015 в 22:27
Другие вопросы по тегам:

Похожие вопросы: