it-swarm-es.com

¿Cómo identificar si una página web se está cargando dentro de un iframe o directamente en la ventana del navegador?

Estoy escribiendo una aplicación de facebook basada en iframe. Ahora quiero usar la misma página html para representar el sitio web normal y la página de lienzo dentro de facebook. ¿Quiero saber si puedo determinar si la página se ha cargado dentro del iframe o directamente en el navegador?

515
akshat

Los navegadores pueden bloquear el acceso a window.top debido a la misma política de Origen . IE errores también tienen lugar. Aquí está el código de trabajo:

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

top y self son ambos objetos window (junto con parent), por lo que está viendo si su ventana es la ventana superior.

962
Greg

El método window.frameElement devuelve el elemento (por ejemplo, iframe o object) en el que está incrustada la ventana, o null si navega en un contexto de nivel superior:

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

Este es un HTML Standard con soporte básico en todos los navegadores modernos.

78

RoBorg tiene razón, pero quería añadir una nota al margen.

En IE7/IE8, cuando Microsoft agregó pestañas a su navegador, rompieron una cosa que causará estragos en su JS si no tiene cuidado.

Imagina este diseño de página:

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

Ahora en el cuadro "baz" haces clic en un enlace (sin destino, se carga en el cuadro "baz") funciona bien.

Si la página que se carga, llamémosla special.html, usa JS para verificar si "tiene" un marco primario llamado "barra", devolverá verdadero (esperado).

Ahora digamos que la página special.html cuando se carga, comprueba el marco principal (busca la existencia y su nombre, y si es "barra", se vuelve a cargar en el marco de la barra, por ejemplo,.

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

Hasta ahora tan bueno. Ahora viene el error.

Digamos que en lugar de hacer clic en el enlace original como de costumbre, y al cargar la página special.html en el marco "baz", hiciste un clic intermedio o elegiste abrirlo en una nueva pestaña.

Cuando esa nueva pestaña se cargue ( ¡sin marcos principales! ) IE ingresará a un bucle sin fin de carga de páginas! porque IE "copia sobre" la estructura del cuadro en JavaScript de modo que la nueva pestaña TIENE un padre, y ese padre TIENE el nombre de "barra".

La buena noticia es que revisando:

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

en esa nueva pestaña devuelve verdadero, y así puedes probar esta condición impar.

25
scunliffe

La respuesta aceptada no me funcionó dentro del script de contenido de una extensión de Firefox 6.0 (Addon-SDK 1.0): Firefox ejecuta el script de contenido en cada uno: la ventana de nivel superior y en todos los iframes.

Dentro del script de contenido obtengo los siguientes resultados:

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

Lo extraño de esta salida es que siempre es lo mismo, independientemente de si el código se ejecuta dentro de un iframe o la ventana de nivel superior.

Por otro lado, Google Chrome parece ejecutar mi script de contenido solo una vez dentro de la ventana de nivel superior, por lo que lo anterior no funcionaría en absoluto.

Lo que finalmente me funcionó en un script de contenido en ambos navegadores es esto:

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

Sin iframes, esto imprime 0:0, en una ventana de nivel superior que contiene un marco, imprime 1:1, y en el único iframe de un documento imprime 0:1.

Esto permite que mi extensión determine en ambos navegadores si hay algunos iframes presentes, y adicionalmente en Firefox si se ejecuta dentro de uno de los iframes.

18
magnoz

No estoy seguro de cómo funciona este ejemplo para los navegadores web más antiguos, pero uso esto para IE, Firefox y Chrome sin ningún problema:

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

Estoy usando esto:

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

Use esta función de javascript como un ejemplo de cómo lograr esto.

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

En realidad, solía marcar window.parent y funcionó para mí, pero últimamente window es un objeto cíclico y siempre tiene una clave principal, iframe o no iframe.

Como los comentarios sugieren una comparación difícil con windows.parent funciona. No estoy seguro de si esto funcionará si iframe es exactamente la misma página web que el principal.

window === window.parent;
1
Jabran Saeed

El mejor script para romper el marco del navegador heredado

Las otras soluciones no funcionaron para mí. Éste funciona en todos los navegadores:

Una forma de defenderse contra el clickjacking es incluir un script "para romper el marco" en cada página que no deba ser enmarcado. La siguiente metodología evitará que una página web se enmarque incluso en los navegadores antiguos, que no son compatibles con el encabezado de opciones de X-Frame.

En el documento HEAD elemento, agregue lo siguiente:

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

Primero aplique una identificación al propio elemento de estilo:

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

De esta manera, todo puede estar en el documento HEAD y solo necesita un método/taglib en su API.

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

1
Albert Olivé

Dado que está preguntando en el contexto de una aplicación de Facebook, es posible que desee considerar la detección de esto en el servidor cuando se realiza la solicitud inicial. Facebook pasará un montón de datos de la cadena de consulta, incluida la clave fb_sig_user si se llama desde un iframe.

Dado que probablemente necesite verificar y usar estos datos de todas formas en su aplicación, utilícelos para determinar el contexto apropiado para renderizar.

1
HectorMac

Esto terminó siendo la solución más simple para mí.

    <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