Pregunta

La función de evaluación es una forma potente y sencilla de generar código dinámicamente, entonces, ¿cuáles son las advertencias?

¿Fue útil?

Solución

  1. Uso inadecuado de evaluar Abre su código para ataques de inyección

  2. Depuración puede ser más desafiante (sin números de línea, etc.)

  3. El código evaluado se ejecuta más lento (no hay oportunidad de compilar/almacenar en caché el código evaluado)

Editar:Como señala @Jeff Walden en los comentarios, el punto 3 es menos cierto hoy que en 2008.Sin embargo, si bien es posible que se almacenen en caché los scripts compilados, esto solo se limitará a los scripts que se evalúen repetidamente sin modificaciones.Un escenario más probable es que esté evaluando scripts que han sufrido ligeras modificaciones cada vez y, como tales, no se pudieron almacenar en caché.Digamos que ALGÚN código evaluado se ejecuta más lentamente.

Otros consejos

La evaluación no siempre es mala.Hay ocasiones en las que es perfectamente apropiado.

Sin embargo, eval es actual e históricamente sobreutilizado masivamente por personas que no saben lo que están haciendo.Desafortunadamente, eso incluye a personas que escriben tutoriales de JavaScript y, en algunos casos, esto puede tener consecuencias de seguridad o, más a menudo, simples errores.Entonces, cuanto más podamos hacer para poner un signo de interrogación sobre la evaluación, mejor.Cada vez que usas eval necesitas verificar lo que estás haciendo, porque es probable que puedas hacerlo de una manera mejor, más segura y más limpia.

Para dar un ejemplo muy típico, para establecer el color de un elemento con una identificación almacenada en la variable 'patata':

eval('document.' + potato + '.style.color = "red"');

Si los autores del tipo de código anterior tuvieran una idea sobre los conceptos básicos de cómo funcionan los objetos JavaScript, se habrían dado cuenta de que se pueden usar corchetes en lugar de nombres de puntos literales, obviando la necesidad de evaluación:

document[potato].style.color = 'red';

...que es mucho más fácil de leer y tiene menos errores.

(Pero entonces, alguien que /realmente/ supiera lo que hacía diría:

document.getElementById(potato).style.color = 'red';

que es más confiable que el viejo y dudoso truco de acceder a elementos DOM directamente desde el objeto del documento).

Creo que es porque puede ejecutar cualquier función de JavaScript desde una cadena.Su uso facilita que las personas inyecten código malicioso en la aplicación.

Me vienen a la mente dos puntos:

  1. Seguridad (pero siempre que usted mismo genere la cadena para evaluarla, esto podría no ser un problema)

  2. Actuación:Hasta que no se conozca el código a ejecutar, no se podrá optimizar.(sobre javascript y rendimiento, ciertamente Presentación de Steve Yegge)

Pasar la entrada del usuario a eval() es un riesgo de seguridad, pero también cada invocación de eval() crea una nueva instancia del intérprete de JavaScript.Esto puede ser un acaparador de recursos.

Por lo general, solo es un problema si pasa la entrada del usuario de evaluación.

Principalmente, es mucho más difícil de mantener y depurar.Es como un goto.Puede usarlo, pero hace que sea más difícil encontrar problemas y que sea más difícil para las personas que puedan necesitar realizar cambios más adelante.

Una cosa a tener en cuenta es que a menudo puedes usar eval() para ejecutar código en un entorno que de otro modo estaría restringido; los sitios de redes sociales que bloquean funciones específicas de JavaScript a veces pueden ser engañados dividiéndolos en un bloque de evaluación.

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

Entonces, si está buscando ejecutar algún código JavaScript donde de otro modo no estaría permitido (Mi espacio, te estoy mirando...) entonces eval() puede ser un truco útil.

Sin embargo, por todas las razones mencionadas anteriormente, no deberías usarlo para tu propio código, donde tienes control total; simplemente no es necesario y es mejor relegarlo al estante de los 'trucos complicados de JavaScript'.

A menos que permita que eval() sea un contenido dinámico (a través de cgi o entrada), es tan seguro y sólido como todos los demás JavaScript de su página.

Junto con el resto de las respuestas, no creo que las declaraciones de evaluación puedan tener una minimización avanzada.

Es un posible riesgo de seguridad, tiene un alcance de ejecución diferente y es bastante ineficiente, ya que crea un entorno de scripting completamente nuevo para la ejecución del código.Consulte aquí para obtener más información: evaluar.

Sin embargo, es bastante útil y si se usa con moderación puede agregar muchas funciones buenas.

A menos que esté 100% seguro de que el código que se está evaluando proviene de una fuente confiable (generalmente su propia aplicación), entonces es una forma segura de exponer su sistema a un ataque de secuencias de comandos entre sitios.

Sé que esta discusión es vieja, pero me gusta mucho. este enfoque de Google y quería compartir ese sentimiento con otros;)

La otra cosa es que cuanto mejor obtienes, más intentas entender y finalmente no crees que algo es bueno o malo solo porque alguien lo dijo :) Esto es muy inspirador video eso me ayudó a pensar más por mí mismo :) LAS BUENAS PRÁCTICAS son buenas, pero no las uses sin pensar :)

No es necesariamente tan malo siempre que sepas en qué contexto lo estás usando.

Si su aplicación está usando eval() para crear un objeto a partir de algún JSON que ha regresado de un Solicitud XMLHttp a su propio sitio, creado por su código del lado del servidor de confianza, probablemente no sea un problema.

De todos modos, el código JavaScript del lado del cliente que no es de confianza no puede hacer mucho.Siempre que lo que estás ejecutando eval() proviene de una fuente razonable, estás bien.

Reduce en gran medida su nivel de confianza sobre la seguridad.

Si desea que el usuario ingrese algunas funciones lógicas y evalúe Y el O entonces la función de evaluación de JavaScript es perfecta.Puedo aceptar dos cadenas y eval(uate) string1 === string2, etc.

Si detecta el uso de eval() en su código, recuerde el mantra "eval() es malo".

Esta función toma una cadena arbitraria y la ejecuta como código JavaScript.Cuando el código en cuestión se conoce de antemano (no se determina en tiempo de ejecución), no hay razón para usar eval ().Si el código se genera dinámicamente en tiempo de ejecución, a menudo hay una mejor manera de lograr el objetivo sin eval ().Por ejemplo, solo usar notación de soporte cuadrado para acceder a propiedades dinámicas es mejor y más simple:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

Usando eval() También tiene implicaciones de seguridad, porque podría estar ejecutando código (por ejemplo, proveniente de la red) que ha sido manipulado.Este es un antipatrón común cuando se trata de una respuesta JSON de una solicitud Ajax.En esos casos, es mejor usar los métodos integrados de los navegadores para analizar la respuesta JSON para asegurarse de que sea seguro y válido.Para navegadores que no son compatibles JSON.parse() Nativamente, puede usar una biblioteca de json.org.

También es importante recordar que pasar cadenas a setInterval(), setTimeout(), y el Function() constructor es, en su mayor parte, similar a usar eval() y, por lo tanto, debe evitarse.

Detrás de escena, JavaScript todavía tiene que evaluar y ejecutar la cadena que pasa como código de programación:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

El uso del nuevo constructor de función () es similar a Eval () y debe abordarse con cuidado.Podría ser una construcción poderosa pero a menudo se usa mal.Si absolutamente debes usar eval(), puedes considerar usar new Function() en su lugar.

Existe un pequeño beneficio potencial porque el código evaluado en la nueva función () se ejecutará en un alcance de la función local, por lo que cualquier variable definida con VAR en el código que se está evaluando no se convertirá en globos automáticamente.

Otra forma de evitar las globales automáticas es ajustar eleval() llamar a una función inmediata.

Además de los posibles problemas de seguridad si ejecuta código enviado por el usuario, la mayoría de las veces existe una manera mejor que no implica volver a analizar el código cada vez que se ejecuta.Las funciones anónimas o propiedades de objetos pueden reemplazar la mayoría de los usos de eval y son mucho más seguras y rápidas.

Esto puede convertirse en un problema mayor a medida que la próxima generación de navegadores presente algo parecido a un compilador de JavaScript.Es posible que el código ejecutado a través de Eval no funcione tan bien como el resto de su JavaScript en estos navegadores más nuevos.Alguien debería hacer algún perfil.

Este es uno de los buenos artículos que hablan sobre la evaluación y cómo no es un mal:http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

No digo que debas salir corriendo y comenzar a usar eval () en todas partes.De hecho, hay muy pocos casos de uso buenos para ejecutar eval () en absoluto.Definitivamente, existen preocupaciones con la claridad del código, la depugabilidad y ciertamente el rendimiento que no debe pasarse por alto.Pero no debe tener miedo de usarlo cuando tenga un caso en el que Eval () tenga sentido.Intente no usarlo primero, pero no permita que nadie lo asuste a pensar que su código es más frágil o menos seguro cuando eval () se usa adecuadamente.

eval() es muy poderoso y puede usarse para ejecutar una declaración JS o evaluar una expresión.Pero la pregunta no es sobre los usos de eval() sino que digamos cómo la cadena que ejecuta eval() se ve afectada por una parte maliciosa.Al final estarás ejecutando código malicioso.El poder conlleva una gran responsabilidad.Así que úsalo sabiamente si lo estás usando.Esto no está muy relacionado con la función eval() pero este artículo tiene bastante buena información: http://blogs.popart.com/2009/07/javascript-injection-attacks/Si está buscando los conceptos básicos de eval(), mire aquí:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

No intentaré refutar nada de lo dicho hasta ahora, pero ofreceré este uso de eval() que (hasta donde yo sé) no se puede hacer de otra manera.Probablemente haya otras formas de codificar esto, y probablemente formas de optimizarlo, pero esto se hace a mano y sin ninguna extravagancia en aras de la claridad para ilustrar un uso de eval que realmente no tiene otras alternativas.Eso es:nombres de objetos dinámicos (o más exactamente) creados mediante programación (a diferencia de valores).

//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
        if(i === 0){
            namespaceToTest = namespaceParts[i];
        }
        else{
            namespaceToTest = namespaceToTest + "." + namespaceParts[i];
        }

        if(eval('typeof ' + namespaceToTest) === "undefined"){
            eval(namespaceToTest + ' = {}');
        }
    }
    return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
    //Code goes here
    //this.MyOtherMethod("foo"));  // => "foo"
    return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

EDITAR:Por cierto, no sugeriría (por todas las razones de seguridad señaladas hasta ahora) que base los nombres de los objetos en la entrada del usuario.Aunque no puedo imaginar ninguna buena razón por la que quieras hacer eso.Aún así, pensé en señalar que no sería una buena idea :)

El motor JavaScript tiene una serie de optimizaciones de rendimiento que realiza durante la fase de compilación.Algunos de estos se reducen a poder analizar esencialmente estáticamente el código a medida que se ejecuta y predeterminar dónde están todas las declaraciones de variables y funciones, de modo que se requiera menos esfuerzo para resolver identificadores durante la ejecución.

Pero si el motor encuentra una evaluación (...) en el código, esencialmente tiene que asumir que todo su conocimiento de la ubicación del identificador puede no ser válido, porque no puede saber en el momento de la lectura exactamente qué código puede pasar a la evaluación (...) para modificar el alcance léxico, o el contenido del objeto al que puede pasar para crear un nuevo alcance léxico para ser consultado.

En otras palabras, en el sentido pesimista, la mayoría de las optimizaciones que haría no tienen sentido si eval(..) está presente, por lo que simplemente no realiza ninguna optimización.

Esto lo explica todo.

Referencia :

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

No siempre es una mala idea.Tomemos, por ejemplo, la generación de código.Recientemente escribí una biblioteca llamada Hiperbarras que cierra la brecha entre DOM virtual y bigote daliniano.Para ello, analiza una plantilla de manillar y la convierte en hiperíndice que posteriormente es utilizado por virtual-dom.El hiperíndice se genera primero como una cadena y antes de devolverlo, eval() para convertirlo en código ejecutable.he encontrado eval() en esta situación particular, exactamente lo opuesto al mal.

Básicamente de

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

A esto

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
        return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

El rendimiento de eval() No es un problema en una situación como esta porque sólo necesita interpretar la cadena generada una vez y luego reutilizar la salida ejecutable muchas veces.

Puedes ver cómo se logró la generación del código si tienes curiosidad. aquí.

Me atrevería a decir que realmente no importa si usas eval() en javascript que se ejecuta en los navegadores.*(advertencia)

Todos los navegadores modernos tienen una consola de desarrollador donde puede ejecutar JavaScript arbitrario de todos modos y cualquier desarrollador semi-inteligente puede mirar su fuente JS y poner los fragmentos que necesite en la consola de desarrollo para hacer lo que desee.

*Siempre que los puntos finales de su servidor tengan la validación y desinfección correctas de los valores proporcionados por el usuario, no debería importar lo que se analice y evalúe en el javascript del lado del cliente.

Si preguntaras si es adecuado para usar eval() en PHP sin embargo, la respuesta es NO, a menos que usted lista blanca cualquier valor que pueda pasarse a su declaración de evaluación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top