Jak rozpoznać, czy strona internetowa jest ładowany wewnątrz iframe lub bezpośrednio w oknie przeglądarki?

głosy
450

Piszę iframe oparte facebook app. Teraz chcę używać tej samej strony HTML do renderowania normalnej strony internetowej, a także na stronie płótna w facebook. Chcę wiedzieć, czy mogę ustalić, czy strona została załadowana wewnątrz iframe lub bezpośrednio w przeglądarce?

Utwórz 28/11/2008 o 16:45
źródło użytkownik
W innych językach...                            


15 odpowiedzi

głosy
840

Przeglądarki mogą blokować dostęp do window.topz powodu samej polityki pochodzenia . Bugs IE odbywają się także. Oto kod roboczych:

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

topi selfto zarówno windowobiektów (wraz z parent), więc widzisz, jeśli okno jest top okno.

Odpowiedział 28/11/2008 o 16:47
źródło użytkownik

głosy
25

RoBorg jest poprawna, ale chciałem dodać notatkę boczną.

W IE7 / IE8 kiedy Microsoft dodał do swojej przeglądarki Tabs złamali jedną rzecz, która spowoduje spustoszenie z JS, jeśli nie jesteś ostrożny.

Wyobraź sobie ten układ strony:

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

Teraz w ramce „Baz” kliknięciu łącza (nie cel, ładunki w „baz” ramka) działa prawidłowo.

Jeżeli strona, która zostanie załadowana, pozwala wywołać special.html używa JS, aby sprawdzić, czy „to” ma ramę nadrzędnego o nazwie „bar” zwróci true (spodziewane).

Teraz powiedzmy, że strona special.html gdy ładuje, sprawdza ramki nadrzędnej (dla istnienia i jego nazwy, a jeśli jest to „bar” to ładuje się w ramce bar. Np

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

Jak na razie dobrze. Teraz jest bug.

Powiedzmy, zamiast klikania na oryginalnym linkiem jak normalne, a ładowanie strony special.html w „baz” ramki, to w średnim lub kliknięciu go wybrał, aby otworzyć go w nowej karcie.

Kiedy to nowe obciążenia zakładkę ( bez ramek macierzystych w ogóle! ) IE wejdzie nieskończoną pętlę ładowania strony! Ponieważ „kopie ponad”, czyli konstrukcji ramy w JavaScript, takie, że nowa karta ma rodzica, a rodzic ma nazwę „bar”.

Dobrą wiadomością jest to, że kontrola:

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

w tej nowej karcie nie zwróci true, a więc można przetestować w tym dziwnym stanie.

Odpowiedział 28/11/2008 o 18:53
źródło użytkownik

głosy
1

Skoro pytasz w kontekście aplikacji Facebooku, może warto rozważyć wykrywania tego na serwerze, gdy początkowy wniosek został złożony. Facebook przejdzie wzdłuż bandą kwerendy danych w tym kluczu fb_sig_user jeśli jest wywołana z iframe.

Ponieważ prawdopodobnie trzeba sprawdzić i wykorzystać te dane w każdym razie w swojej aplikacji, użyj go w celu określenia odpowiedniego kontekstu renderowania.

Odpowiedział 11/12/2008 o 23:04
źródło użytkownik

głosy
2

Użyj tej funkcji javascript jako przykład, w jaki sposób tego dokonać.

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;
}
Odpowiedział 21/09/2011 o 03:32
źródło użytkownik

głosy
16

Przyjęte rozwiązanie nie działa dla mnie wewnątrz skryptu content Firefox 6.0 Extension (Addon-SDK 1.0): Firefox uruchamia skrypt treści w każdy: okno najwyższego poziomu i we wszystkich iframe.

Wewnątrz skryptu zawartości uzyskać następujące wyniki:

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

Dziwną rzeczą tego wyjścia jest to, że zawsze taka sama, niezależnie czy kod jest uruchamiany wewnątrz iframe lub okna najwyższego poziomu.

Z drugiej strony Google Chrome wydaje się wykonać mój skrypt treści tylko raz w oknie najwyższego poziomu, więc powyższe nie działa w ogóle.

Co ostatecznie pracował dla mnie w treści skryptu w obu przeglądarkach jest to:

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

Bez iframe Drukuje 0:0, w oknie najwyższego poziomu zawierającego jedną klatkę to drukuje 1:1, a jedyną iframe dokumentu drukuje 0:1.

Pozwala to moje rozszerzenie do określenia w obu przeglądarkach, czy są jakieś iframes obecny, a dodatkowo w Firefoksie jeśli jest prowadzony wewnątrz jednego z iframe.

Odpowiedział 14/10/2011 o 15:32
źródło użytkownik

głosy
-1

Jest to starożytny kawałek kodu, który użyłem kilka razy:

if (parent.location.href == self.location.href) {
    window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}
Odpowiedział 25/10/2011 o 04:57
źródło użytkownik

głosy
5

Używam tego:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
Odpowiedział 20/06/2012 o 11:04
źródło użytkownik

głosy
-3
if (window.frames.length != parent.frames.length) { page loaded in iframe }

Ale tylko wtedy, gdy liczba iframe różni się w swoją stronę i strony, które ładują cię w iframe. Dokonaj no iframe na swojej stronie aby mieć 100% gwarancję wyniku tego kodu

Odpowiedział 27/10/2012 o 16:31
źródło użytkownik

głosy
-4

Napisać ten skrypt na każdej stronie

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

Następnie zostanie ona automatycznie przekierowuje do strony głównej.

Odpowiedział 08/02/2013 o 07:15
źródło użytkownik

głosy
0

Jeśli chcesz wiedzieć, czy użytkownik ma dostęp do aplikacji z zakładki strony na Facebooku lub czekiem płótnie dla podpisanego wniosku. Jeśli nie dostać, chyba że użytkownik nie korzysta z Facebooka. Aby upewnić się potwierdzić signed_request strukturę pól i pól treści.

Z php-SDK można uzyskać podpisanego wniosku takiego:

$signed_request = $facebook->getSignedRequest();

Możesz przeczytać więcej na temat podpisanego wniosku tutaj:

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

i tu:

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

Odpowiedział 17/06/2013 o 19:08
źródło użytkownik

głosy
64

window.frameElementZwraca element (na przykład <iframe> lub <>) przedmiotów, w którym okno jest osadzony lub zerowy, jeżeli okno jest na najwyższym poziomie. Tak wygląda kod identyfikujący

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

Jest to standardowa i raczej nowa metoda. To dokładnie działa w Chrome i Firefox. Nie mogę polecić go jako uniwersalnego rozwiązania, ale należy wspomnieć tutaj myślę.

Odpowiedział 07/09/2013 o 23:55
źródło użytkownik

głosy
1

I rzeczywiście używany do sprawdzania window.parent i pracował dla mnie, ale ostatnio okno jest cyklicznym obiekt i zawsze ma klucz nadrzędny, iframe lub nie iframe.

Jak tłumaczy komentarz ciężko porównać z dziełami window.parent. Nie wiem, czy to będzie działać, jeśli iframe jest dokładnie taka sama strona jako rodzica.

window === window.parent;
Odpowiedział 04/03/2014 o 04:47
źródło użytkownik

głosy
3

Nie jestem pewien, jak ten przykład działa dla starszych przeglądarek internetowych, ale używam tego dla IE, Firefox i Chrome bez emisyjna:

var iFrameDetection = (window === window.parent) ? false : true;
Odpowiedział 19/11/2015 o 09:30
źródło użytkownik

głosy
0

Best-for-teraz ramki Legacy Browser Łamanie Script

Inne rozwiązania nie pracował dla mnie. Ten działa na wszystkich przeglądarkach:

Jednym ze sposobów obrony przed clickjacking ma obejmować „frame-breaker” skrypt na każdej stronie, które nie powinny być oprawione. Poniższa metodologia uniemożliwi stronę internetową z wrobiony nawet w przeglądarkach starszych, które nie obsługują X-Frame-Options-header.

W elemencie HEAD dokumentu, należy dodać następujące:

<style id="antiClickjack">body{display:none !important;}</style>

Najpierw zastosować identyfikator do samego elementu stylu:

<script type="text/javascript">
   if (self === top) {
       var antiClickjack = document.getElementById("antiClickjack");
       antiClickjack.parentNode.removeChild(antiClickjack);
   } else {
       top.location = self.location;
   }
</script>

W ten sposób wszystko, co może być w HEAD dokumentu i trzeba tylko jedna metoda / TagLib w API.

Numer referencyjny: https://www.codemagi.com/blog/post/194

Odpowiedział 12/04/2018 o 09:24
źródło użytkownik

głosy
0

Ten zakończony jest najprostszym rozwiązaniem dla mnie.

    <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>
Odpowiedział 25/07/2018 o 01:15
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more