Jak rozpoznać, czy strona jest ładowana wewnątrz ramki iframe lub bezpośrednio do okna przeglądarki?

Piszę aplikację facebook opartą na iframe. Teraz chcę użyć tej samej strony html do renderowania normalnej strony internetowej, a także strony canvas w facebook. Chcę wiedzieć, Czy Mogę określić, czy strona została załadowana wewnątrz ramki iframe czy bezpośrednio w przeglądarce?

Author: akshat, 2008-11-28

15 answers

Przeglądarki mogą zablokować dostęp do window.topze względu na tę samą politykę pochodzenia. Błędy IE również mają miejsce. Oto kod roboczy:

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

top i self są obie window obiekty (wraz z parent), więc widzisz, czy Twoje okno jest górnym oknem.

 883
Author: Greg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-14 19:15:14

window.frameElement Zwraca element (taki jak

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

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

 69
Author: Konstantin Smolyanin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-18 17:44:20

RoBorg ma rację, ale chciałem dodać dodatkową notkę.

W IE7 / IE8 kiedy Microsoft dodał karty do swojej przeglądarki złamali jedną rzecz, która spowoduje spustoszenie w Twoim JS, jeśli nie będziesz 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" klikasz link (bez celu, ładuje się w ramce "baz") działa dobrze.

Jeśli strona zostanie załadowana, nazwijmy ją specjalną.html, używa JS aby sprawdzić czy " it "ma ramkę nadrzędną o nazwie" bar " zwróci prawda (oczekiwana).

Teraz powiedzmy, że specjalny.strona html podczas ładowania sprawdza ramkę nadrzędną (pod kątem istnienia i jej nazwy, a jeśli jest to "bar" to przeładowuje się w ramce bar. np.

if(window.parent && window.parent.name == 'bar'){
  window.parent.location = self.location;
}
Jak na razie dobrze. Teraz nadchodzi robal.

powiedzmy, że zamiast klikać oryginalny link jak zwykle i ładować specjalną.strona html w ramce "baz", kliknąłeś ją lub wybrałeś, aby otworzyć ją w nowej karcie.

Kiedy nowa karta się ładuje (z żadnych ramek dla rodziców!) IE wejdzie w niekończącą się pętlę ładowania strony! ponieważ IE "kopiuje" strukturę ramki w JavaScript tak, że nowa karta ma rodzica, a ten rodzic ma nazwę "bar".

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

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

W tej nowej karcie zwraca true, a więc możesz sprawdzić ten dziwny warunek.

 25
Author: scunliffe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-28 17:53:15

Zaakceptowana odpowiedź nie zadziałała w skrypcie zawartości rozszerzenia Firefoksa 6.0 (Addon-SDK 1.0): Firefox wykonuje skrypt zawartości w każdym: oknie najwyższego poziomu i we wszystkich ramkach iFrame.

Wewnątrz skryptu content otrzymuję następujące wyniki:

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

Dziwną rzeczą w tym wyjściu jest to, że zawsze jest to samo, niezależnie od tego, czy kod jest uruchamiany wewnątrz ramki iframe, czy okna najwyższego poziomu.

Z drugiej strony Google Chrome wydaje się wykonywać moje skrypt zawartości tylko raz w oknie najwyższego poziomu, więc powyższy w ogóle nie działa.

To, co w końcu zadziałało dla mnie w skrypcie treści w obu przeglądarkach, to:

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

Bez ramek iFrame drukuje 0:0, w oknie najwyższego poziomu zawierającym jedną ramkę drukuje 1:1, a w jedynej ramce iframe dokumentu drukuje 0:1.

To pozwala mojemu rozszerzeniu określić w obu przeglądarkach, czy istnieją jakieś ramki iFrame obecne, a dodatkowo w Firefoksie, jeśli jest uruchomiony wewnątrz jednego z iframes.

 17
Author: magnoz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-14 14:32:23

Używam tego:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
 5
Author: mikewolf78,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-20 11:01:14

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

var iFrameDetection = (window === window.parent) ? false : true;
 3
Author: portal TheAnGeLs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 13:59:18

Użyj tej funkcji javascript jako przykład, jak to osiągnąć.

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
Author: Rolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-21 02:32:51

Ponieważ pytasz w kontekście aplikacji facebook, warto rozważyć wykrycie tego na serwerze, gdy początkowe żądanie jest wykonane. Facebook przekaże kilka danych querystring, w tym klucz fb_sig_user, jeśli zostanie wywołany z ramki iframe.

Ponieważ prawdopodobnie musisz sprawdzić i użyć tych danych w swojej aplikacji, użyj ich, aby określić odpowiedni kontekst do renderowania.

 1
Author: HectorMac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-11 22:04:42

Best-for-now skrypt łamania ramek przeglądarki

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

Jednym ze sposobów obrony przed clickjackingiem jest umieszczenie na każdej stronie skryptu "frame-breaker", który nie powinien być ramkowany. Poniższa metodologia uniemożliwi ramkowanie strony internetowej nawet w starszych przeglądarkach, które nie obsługują nagłówka X-Frame-Options.

W elemencie nagłówka dokumentu dodaj:

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

Pierwszy zastosuj ID 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 może znajdować się w nagłówku dokumentu i potrzebujesz tylko jednej metody/taglib w swoim API.

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

 1
Author: Albert Olivé,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-12 11:09:41

Właściwie sprawdzałem okno.parent i u mnie działało, ale ostatnio window jest obiektem cyklicznym i zawsze ma klucz rodzica, iframe lub brak iframe.

Jako, że komentarze sugerują trudne porównanie z oknem.rodzic pracuje. Nie wiem, czy to zadziała, jeśli iframe jest dokładnie tą samą stroną co rodzic.

window === window.parent;
 1
Author: Jabran Saeed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-16 08:43:11

Jeśli chcesz wiedzieć, czy użytkownik uzyskuje dostęp do Twojej aplikacji z zakładki facebook page lub canvas, sprawdź podpisane żądanie. Jeśli tego nie rozumiesz, prawdopodobnie użytkownik nie ma dostępu z facebook. Aby potwierdzić strukturę pól signed_request i zawartość pól.

Z PHP-sdk można uzyskać podpisane żądanie w następujący sposób:

$signed_request = $facebook->getSignedRequest();

Możesz przeczytać więcej o podpisanym żądaniu tutaj:

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

I tutaj:

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

 0
Author: Joao Belchior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-17 18:08:49

To skończyło się dla mnie najprostszym rozwiązaniem.

    <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
Author: Alex Roseland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-25 01:15:41

To starożytny fragment 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';
}
 -1
Author: Error601,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-25 03:57:35
if (window.frames.length != parent.frames.length) { page loaded in iframe }

Ale tylko wtedy, gdy liczba ramek iFrame różni się w twojej stronie i stronie, która ładuje cię w iframe. Nie rób iframe na swojej stronie, aby mieć 100% gwarancję wyniku tego kodu

 -3
Author: Vova Popov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-27 15:31:39

Napisz ten javascript na każdej stronie

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

Następnie automatycznie przekieruje do strony głównej.

 -4
Author: shibin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-16 21:50:55