Bir web sayfasının iframe'in içine mi yoksa doğrudan tarayıcı penceresine yüklenip yüklenmediğini nasıl belirleyebilirim?


596

Iframe tabanlı bir facebook uygulaması yazıyorum. Şimdi normal web sitesini ve aynı zamanda facebook içindeki tuval sayfasını oluşturmak için aynı html sayfasını kullanmak istiyorum. Sayfanın iframe'in içine mi yoksa doğrudan tarayıcıya mı yükleneceğini belirleyebilir miyim?


2
Birkaç güzel yol (yorumlar dahil): tommcfarlin.com/check-if-a-page-is-in-an-iframe
simhumileco

Yanıtlar:


1107

Tarayıcılar, aynı başlangıç ​​politikasıwindow.top nedeniyle erişimi engelleyebilir . IE hataları da yer alır. İşte çalışma kodu:

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

topve selfher ikisi de window(birlikte parent) nesneler olduğundan, pencerenizin en üst pencere olup olmadığını görüyorsunuz.


4
Firefox'ta bu iyi çalışıyor gibi görünüyor. Diğer tarayıcılarda da çalışıyor mu?
akshat

5
Bir iframe içinde iframe içeren bir sayfaya sahip olmak, üst iframe sayfamın içine gömülmüşse çocuğum iframe'inden test etmek için, (parent === top)
sglessard

7
@sglessard Alt sayfa ve üst öğe farklı alan adlarından geliyorsa, Firefox Aynı Köken Politikası (www.w3.org/Security/wiki/Same_Origin_Policy) için şikayet edecek ve kod çalışmaz
Gaurang Jadia

18
Bu IE 11, 10 ve 9'da benim için çalışıyor. Ayrıca FF ve Opera'da ve elbette Chrome'da da çalışır. Bununla ilgili herhangi bir sorunla karşılaşmadım.
jeremysawesome

4
1995'te en son sallananlar için, teknoloji , veya içeriğinden çalıştırıldığında window.self !== window.topgeri döner . trueframe iframe
Jeromy Fransızca

84

Üst window.frameElementöğe ile aynı başlangıç ​​noktasında bir iframe'deyken, yöntem pencerenin katıştırıldığı öğeyi (örneğin iframeveya object) döndürür . Aksi takdirde, üst düzey bir bağlamda göz atıyorsanız veya üst ve alt çerçevenin farklı kökenleri varsa, olarak değerlendirilir null.

window.frameElement
  ? 'embedded in iframe or object'
  : 'not embedded or cross-origin'

Bu, tüm modern tarayıcılarda temel desteği olan bir HTML Standardıdır .


2
W3C'yeframeElement göre, okuma girişiminde bulunma , çapraz kökenli iframe'lerde bir SecurityError istisnası atacaktır ( WHATWG bunun yerine null döndürmesi gerektiğini söylüyor). Yani bunu bir ifadenin içine sarmak isteyebilirsiniz . try...catch
Oriol

5
nulliçeri ve dışarı almaiframe
OlehZiniak

4
MDN'deki açıklama, "içine yerleştirilmiş olan belgenin farklı bir kaynağı varsa (farklı bir alan adından yerleştirilmiş gibi), bunun geçersiz olduğunu belirtir."
xeophin

Sadece dönüşün ne olması gerektiğini Returns the element (such as <iframe> or <object>) in which the window is embedded, or null if the element is either top-level or is embedded into a document with a different script origin; that is, in cross-origin situations.
anlamak

26

RoBorg doğru, ama bir yan not eklemek istedim.

IE7 / IE8'de Microsoft tarayıcılarına Sekmeler eklediğinde, dikkatli olmazsanız JS'nize zarar verecek bir şeyi kırdılar.

Bu sayfa düzenini düşünün:

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

Şimdi "baz" karesinde bir linke tıklıyorsunuz (hedef yok, "baz" karesine yükler) iyi çalışıyor.

Yüklenen sayfa bunu special.html olarak adlandıralım, "it" öğesinin "bar" adında bir üst kareye sahip olup olmadığını kontrol etmek için JS kullanır ve true (beklenen) döndürür.

Şimdi special.html sayfasının yüklendiğinde, üst çerçeveyi kontrol ettiğini (varlığını ve adını ve "bar" ise kendisini çubuk çerçevesine yeniden yüklediğini varsayalım.

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

Çok uzak çok iyi. Şimdi hata geliyor.

Diyelim ki normal gibi orijinal bağlantıya tıklamak ve özel.html sayfasını "baz" çerçevesine yüklemek yerine, orta tıklatıp yeni bir Sekmede açmayı seçtiniz.

Bu yeni sekme yüklendiğinde ( hiç ana çerçeve olmadan! ) IE, sonsuz bir sayfa yükleme döngüsü girecektir!çünkü IE, yeni sekmenin bir üst öğeye sahip olacağı ve üst öğenin "bar" adını taşıdığı şekilde JavaScript'teki çerçeve yapısını "kopyalar".

İyi haber şu ki:

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

bu yeni sekmede true değerini döndürür ve böylece bu garip koşulu test edebilirsiniz.


Bu arada hata giderildi mi? IE8'de çoğaltamıyorum. Her zaman doğru olurum window.parent.
user123444555621

1
Emin değilim - test paketimi tekrar IE9 ve altına karşı çalıştıracağım ve bir güncelleme yayınlayacağım.
scunliffe

18

Kabul edilen cevap benim için bir Firefox 6.0 Uzantısının (Addon-SDK 1.0) içerik betiğinde işe yaramadı: Firefox içerik betiğini her birinde üst düzey pencerede ve tüm iframe'lerde yürütür.

İçerik betiğinin içinde aşağıdaki sonuçları alıyorum:

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

Bu çıktıdaki garip şey, kodun bir iframe içinde mi yoksa üst düzey pencerede mi çalıştığından bağımsız olarak her zaman aynı olmasıdır.

Öte yandan Google Chrome, içerik komut dosyamı üst düzey pencerede yalnızca bir kez yürütüyor gibi görünüyor, bu nedenle yukarıdakiler işe yaramayacaktı.

Sonunda benim için her iki tarayıcıda bir içerik komut dosyasında çalışan şey şudur:

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

İç çerçeveler olmadan bu yazdırılır 0:0, yazdırdığı bir çerçeveyi içeren üst düzey bir pencerede 1:1ve yazdırdığı belgenin yalnızca iframe'inde 0:1.

Bu, uzantımın herhangi bir iframe olup olmadığını her iki tarayıcıda ve ayrıca iframe'lerden birinin içinde çalıştırılıyorsa Firefox'ta belirlemesine izin verir.


1
document.defaultView.self === document.defaultView.topVeya deneyin window !== window.top. Firefox'un eklenti SDK'sının içerik komut dosyasında, global selfnesne ana komut dosyasıyla iletişim kurmak için kullanılan bir nesnedir.
Rob W

13

Bu örneğin eski Web tarayıcıları için nasıl çalıştığından emin değilim ama bunu IE, Firefox ve Chrome için kullanmadan kullanıyorum:

var iFrameDetection = (window === window.parent) ? false : true;

6
Veya sadece!(window===window.parent)
CalculatorFeline

11
window! ==
window.parent

5

Bunu kullanıyorum:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);

Neden bunu yapıyorsun: .indexOf("HTMLIFrameElement")?
Luke

.indexOf ('foobarbaz')> -1, "alt dize eşleşmesini" kontrol etmenin bir yoludur (yani 'foobarbaz' dizede bir yerde bulunabilir mi?), ancak normal ifadeler kullanmadan. Mantıksal olarak .match (/ foobarbaz /) öğesine eşdeğerdir. Daha geniş bir tarayıcı yelpazesinde çalışmak için kullanılır (ve alışkanlık dışında veya normal ifade makinelerinin performansı hakkındaki korkular nedeniyle kullanılabilir).
Chuck Kollars

2

Bunu nasıl yapacağınıza ilişkin bir örnek olarak bu javascript işlevini kullanın.

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

Şimdilik En İyi Eski Tarayıcı Çerçevesi Kırma Komut Dosyası

Diğer çözümler benim için işe yaramadı. Bu, tüm tarayıcılarda çalışır:

Tıklamalara karşı savunmanın bir yolu, her sayfaya çerçevelenmemesi gereken bir "çerçeve kırıcı" komut dosyası eklemektir. Aşağıdaki yöntem, bir web sayfasının X-Frame-Options-Üstbilgisini desteklemeyen eski tarayıcılarda bile çerçevelenmesini önleyecektir.

Belge HEAD öğesine aşağıdakileri ekleyin:

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

Önce stil öğesinin kendisine bir kimlik uygulayın:

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

Bu şekilde, her şey HEAD belgesinde olabilir ve API'nizde yalnızca bir yönteme / taglib'e ihtiyacınız vardır.

Referans: https://www.codemagi.com/blog/post/194


1
çerçeveleme tek tehdit, ne itiraz hakkında (iframe etiketi yerine HTML5 nesne etiketini kullanarak) .. .. Bence bu işe yaramayacağını düşünüyorum ..
Raymond Nijland

2
if ( window.location !== window.parent.location ) 
{
      // The page is in an iframe   
} 
else 
{     
      // The page is not in an iframe   
}

1

Bir facebook uygulaması bağlamında sorduğunuz için, ilk istek yapıldığında bunu sunucuda tespit etmeyi düşünebilirsiniz. Facebook, iframe'den çağrılırsa fb_sig_user anahtarı da dahil olmak üzere bir grup sorgu dizisi verisinden geçecektir.

Muhtemelen bu verileri uygulamanızda yine de kontrol etmeniz ve kullanmanız gerektiğinden, oluşturulacak uygun içeriği belirlemek için kullanın.


1

Aslında window.parent kontrol etmek için kullanılır ve benim için çalıştı, ama son zamanlarda pencere döngüsel bir nesne ve her zaman bir üst anahtar, iframe veya iframe vardır.

Yorumlar window.parent ile karşılaştırmak zor önerdiği gibi çalışır. İframe üst öğe ile tamamen aynı web sayfasındaysa bunun işe yarayıp yaramayacağından emin değilim.

window === window.parent;

chrome'da ana pencere bağlamında window.parent === windowdoğrudur. Yani cevabınız yanlış. Ve bu karşılaştırma kontrol için kullanılabilir (en azından kromda, başka bir tarayıcıda test etmedi).
MarkosyanArtur

İFrame bağlamında ÇALIŞMAZ, ancak `if (window === window.parent) {'bunu yapar. Neden işe yaramadığını bilmediğim için seni işaretlemiyorum
www-0av-Com

-1

Birkaç kez kullandığım eski bir kod parçası:

if (parent.location.href == self.location.href) {
    window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}

Eneko Alonso'ya eklemek için: bu işe (parent.location == self.location)
yarar

@piotr_cz, yalnızca aynı menşe politikaya erişime izin veriyorsa çalışır parent.location. Aksi takdirde bir istisna atılır
Dan

-1

Kullanıcının uygulamanıza facebook sayfası sekmesinden veya tuvalden erişip erişmediğini bilmek istiyorsanız İmzalı İstek için kontrol edin. Bunu alamazsanız, muhtemelen kullanıcı facebook'tan erişmiyordur. İmzalı_request alanlarının yapısını ve alan içeriğini doğruladığınızdan emin olmak için.

Php-sdk ile İmzalanmış İsteği şu şekilde alabilirsiniz:

$signed_request = $facebook->getSignedRequest();

İmzalı İstek hakkında daha fazla bilgiyi buradan edinebilirsiniz:

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

ve burada:

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


-1

Bu benim için en basit çözüm oldu.

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

-4
if (window.frames.length != parent.frames.length) { page loaded in iframe }

Ancak yalnızca sayfanızda ve sayfanızda sizi iframe'e yükleyen iframe sayısı farklıysa. Bu kodun% 100 garantisini almak için sayfanızda iframe yapmayın


Pencerenin iframe içinde olup olmadığını belirlemek için çok şık bir çözüm değildir ve parent.frames'ten okuyabileceğinizin garantisi yoktur.
Percy

-4

Bu javascript'i her sayfaya yazın

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

Ardından otomatik olarak ana sayfaya yönlendirir.


4
Yeniden yönlendirme, çerçeve değilseniz. Bu yüzden sitenizde dolaşamam. İkinci olarak, üst sayfadan yönlendirilmesini önlemek için teknikler mevcuttur.
Marius Balčytis
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.