2011-12-08 13 views
17

Actualización: Como esto no ha sido respondido, estoy cambiando la pregunta un poco. Los comentarios sobre la publicación en el blog de Dean vinculado a continuación indican que esta técnica no funciona en Safari.¿Es segura la técnica de "caja de arena iframe"?

Mi pregunta ahora es: ¿funciona la técnica descrita a continuación * en los navegadores modernos y, en particular, alguien puede confirmar si funciona en Safari?

Aquí hay una más reciente blog post. Se dice en un momento:

nativos

espacio aislado ... son compatibles con una variedad de navegadores, incluyendo ... Safari 2.0+

... pero luego dice que la técnica es iframe " compatible con todos los navegadores más importantes, excepto Safari, "y el retroceso que muestra implica hacer cosas raras con constructores falsificados y __proto__ que parece un poco hacky.

Casi me resulta difícil de creer que dos ventanas diferentes en realidad podrían compartir el mismo, por ejemplo, Object.prototype. ¿Qué sucede con los iframes de dominios cruzados? Si modifico prototipos en un marco, ¿se modifican los prototipos del otro marco? Esto parece una preocupación obvia de seguridad. Alguien por favor arroje algo de luz sobre esta situación.

* Por "trabajo" me refiero a My.Object != Object, por lo que los prototipos se pueden modificar en una ventana sin afectar a la otra.


Post original

Sé que esto se ha hecho antes, pero tengo una solución específica en mente, y quiero saber si este tipo de solución se ha discutido antes y donde podría aprender qué tan confiable y bien aceptado es.

La cuestión es cómo extender los tipos nativos en javascript sin interferir en realidad con los tipos en sí mismos, por lo que simplemente alterar Array.prototype no es bueno (quizás otro código esté usando for..in con matrices). Crear un falso constructor que devuelva una matriz nativa con algunas funciones añadidas no parece una buena solución, ya que ampliar los objetos nativos parece mejor. Pero tampoco puede hacer la extensión de estilo normal de javascript dummy function switcharoo con tipos nativos, porque obtendrá errores como "push no es genérico" cuando intente llamar a funciones nativas.

Entonces, la solución que tengo en mente funciona así: cree otra ventana, agregue funcionalidad a prototipos de constructores nativos en esa ventana, y use esos constructores en su programa.

Este ejemplo se extiende Array como My.Array con una función each y String como My.String con una función de alert.

var My = (function(){ 

     // create an iframe to get a separate global scope 
     var iframe = document.createElement('iframe'); 
     iframe.style.height = '0px'; 
     iframe.style.width = '0px'; 
     iframe.style.border = 'none'; 
     iframe.style.position = 'absolute'; 
     iframe.style.left = '-99999px'; 
     document.documentElement.appendChild(iframe); 
     var My = iframe.contentWindow; 

     My.String.prototype.alert = function(){ 
     alert(this); 
     } 

     My.Array.prototype.each = function(callback){ 
     for (var i=0, l=this.length; i<l; i++) { 
      callback(this[i], i); 
     } 
     } 

     return My; 

    }()); 

Una vez más, mi pregunta es si este enfoque se ha discutido antes, cómo se llama, dónde puedo encontrar más información, etc. Me gustaría saber si hay una manera más clara para conseguir otro ámbito global sin usar un iframe, o si es posible, esto fracasará por algún motivo en ciertos motores de JavaScript, o si alguien piensa que es una idea particularmente mala o lo que sea.


Actualización: Creo que la gente está llamando a este tipo de cosas una caja de arena iframe, que no debe confundirse con el atributo iframe caja de arena HTML5.

relacionados:

http://dean.edwards.name/weblog/2006/11/hooray/

http://webreflection.blogspot.com/2008/03/javascript-arrayobject.html

+0

Conseguir un objeto de la ventana limpia es un uso legítimo de iframes, aunque esta técnica es la más utilizada para obtener * * deshacerse de esos métodos adicionales entonces para agregarlos ... – hugomg

+0

missingno, tenemos información disponible sobre cualquier cosa usando actualmente ¿esta tecnica? Tiene un montón de ramificaciones extrañas e imagino que debe haber alguna discusión en la lista de correo en algún lado si se está usando –

+3

Recuerdo haber leído una [presentación] (http://www.slideshare.net/benvinegar/modern-iframe-programming -8281214) de un chico de Disqus. Usan este tipo de truco ya que necesitan poder insertar su código básicamente en cualquier lugar. – hugomg

Respuesta

6

Exploré esta página en varios navegadores (Safari, Opera, IE7-9, Chrome, Firefox) y obtuve resultados consistentes con todo menos con firefox, en firefox los prototipos están en modo de prueba, eso es bueno pero la segunda prueba falla por alguna razón en firefox El prototipo de iframe no se aumenta inmediatamente. Pero esto no importa si no quisiste aumentarlo de todos modos. Podría intentar ejecutarlo en más navegadores para probar.

Tenga en cuenta que esto realmente no prueba ninguna de las peculiaridades, por ejemplo (My.Array().slice devolvería las matrices principales window según el navegador ...) y podría haber más. Entonces diría que es bastante inseguro.

De todos modos, es una exageración y parece demasiado trabajo sin ninguna ganancia real.

<!DOCTYPE html> 
<html> 
<head> 
</head> 
<body> 
<script type="text/javascript"> 
(function(){ 
    var ifr = document.createElement("iframe"), 
     callbacks = [], 
     hasReadyState = "readyState" in ifr; 

    ifr.style.display = "none"; 


    document.body.appendChild(ifr); 
    ifrDoc = ifr.contentWindow.document; 
    ifrDoc.open(); 
    ifrDoc.write("<!DOCTYPE html><html><head></head><body>"+"<"+"script"+">var w = this;"+"</"+"script"+">"+"</body></html>"); 
    ifrDoc.close(); 

    if(hasReadyState) { 

     ifr.onreadystatechange = function(){ 
      if(this.readyState === "complete") { 
       fireCallbacks(); 
      } 
     }; 

    } 

    function fireCallbacks(){ 
     var i, l = callbacks.length; 
     window.My = ifr.contentWindow.w; 

     for(i = 0; i < l; ++i) { 
      callbacks[i](); 
     } 

     callbacks.length = 0; 


    } 

    function checkReady(){ 

     if(hasReadyState && ifr.readyState === "complete") { 
     fireCallbacks(); 
     } 
     else if(!hasReadyState) { 
     fireCallbacks(); 
     } 
    } 

    window.MyReady = function(fn){ 
     if(typeof fn == "function") { 
      callbacks.push(fn); 
     } 
    }; 


window.onload = checkReady; //Change this to DOMReady or whatever 
})() 


MyReady(function(){ 

    My.Object.prototype.test = "hi"; 

    var a = new My.Object(), 
     b = new Object(); 

    console.log(Math.random(), My.Object !== Object && b.test !== "hi", a.test === "hi"); 

}); 
</script> 

</body> 
</html> 
+1

Marcando esto correcto. Después de todo, he decidido no hacer el sandboxing con iframe, por varias razones. –

1

Si usted tiene dos marcos diferentes con contenido cargado desde diferentes dominios, entonces no hay ningún navegador moderno permitirá ningún tipo de interacción en el nivel de JavaScript entre ellos para la seguridad obvia razones. Su mejor opción, por supuesto, sería configurar una prueba y ver qué sucede usted mismo, pero estoy bastante seguro de que lo que está describiendo debería estar seguro en la mayoría de los navegadores.

+0

Sí, pero no tengo un mac. Realmente solo necesito que alguien lo pruebe por mí. También me pregunto si podría fingir comenzando el iframe en un subdominio diferente y luego cambiando document.domain después. –

+0

Ahh bien, sí, yo tampoco tengo una Mac. Yo diría que lo intentéis en IE, Firefox y Chrome. Si pasa en los tres, diría que estás listo para ir. Siempre puedes encontrar a alguien para probarlo en Safari más tarde, pero no creo que deba ser una prioridad de bloqueo para ti. Y, por supuesto, si realmente lo desea, siempre puede configurar una instancia de MacOS en VirtualBox .... –

Cuestiones relacionadas