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?
Jak rozpoznać, czy strona internetowa jest ładowany wewnątrz iframe lub bezpośrednio w oknie przeglądarki?
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.
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.
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.
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;
}
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.
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';
}
Używam tego:
var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
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
Napisać ten skrypt na każdej stronie
if (self == top)
{ window.location = "Home.aspx"; }
Następnie zostanie ona automatycznie przekierowuje do strony głównej.
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/
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ę.
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;
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;
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
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>













