2011-02-21 30 views
13

Necesito evaluar expresiones aritméticas ingresadas por el usuario como "2 * (3 + 4)" en Javascript pero no quiero usar eval por razones de seguridad.Evaluación segura de expresiones aritméticas en Javascript

pude retirar de él todos los caracteres que no sean números o los operadores, pero no estoy seguro de que esto sería seguro de todos modos y que sería bueno si el usuario podría utilizar funciones como cos, sqrt, etc ...

¿Hay alguna biblioteca Javascript que realice evaluación de expresiones aritméticas?

+0

¿A menos que gane la suya no superará ningún problema de seguridad? – James

Respuesta

20

puede intentar JavaScript Expression Evaluator:

Esta biblioteca es una versión modificada de ActionScript Expresión de Raphael Graf Analizador. Cuando escribí el JavaScript Function Plotter, quería una mejor alternativa a que al usar la función eval de JavaScript. No hay riesgo para la seguridad actualmente, porque sólo se puede ejecutar código en su propio navegador, pero no es tan conveniente para matemáticas (Math.pow (2^x) en lugar de 2^x, etc.).

entonces su código será así:

console.info (Parser.evaluate("2 * (3 + 4)")); //prints 14 
+1

¡Gracias! Eso es exactamente lo que estaba buscando, y juro que busqué en Google todas las posibles variaciones en la "evaluación de la expresión" que pude encontrar ... –

1

Puede usar una expresión regular para reemplazar todo excepto su lista blanca. Pero como el javascript se ejecuta en el cliente (a menos que esté ejecutando el servidor http de AOL) cualquiera que pueda modificar las entradas también puede modificar el código, por lo que realmente no lo está haciendo más o menos seguro que ya es.

+1

Depende de si el usuario que escribe la expresión que se evaluará es el mismo que el usuario que evalúa esta expresión. – Bruno

9

Como ya se ha mencionado, la mayoría de los daños que cualquier usuario podría hacer es más o menos lo que ya podían hacer uso de la consola incorporada en cualquiera de las principales navegadores Sin embargo, si desea restringir al usuario a usar las propiedades/métodos Math, puede escribir una expresión regular simple para manejar esto por usted. Algo como esto debería funcionar:

function mathEval (exp) { 
    var reg = /(?:[a-z$_][a-z0-9$_]*)|(?:[;={}\[\]"'!&<>^\\?:])/ig, 
     valid = true; 

    // Detect valid JS identifier names and replace them 
    exp = exp.replace(reg, function ($0) { 
     // If the name is a direct member of Math, allow 
     if (Math.hasOwnProperty($0)) 
      return "Math."+$0; 
     // Otherwise the expression is invalid 
     else 
      valid = false; 
    }); 

    // Don't eval if our replace function flagged as invalid 
    if (!valid) 
     alert("Invalid arithmetic expression"); 
    else 
     try { alert(eval(exp)); } catch (e) { alert("Invalid arithmetic expression"); }; 
} 

Soy consciente de que no desee utilizar eval por razones de seguridad, pero la expresión regular debe dejar muy seguro, ya que descarta cualquier palabra que no son propiedades directas de el objeto Math y la mayoría de los operadores JS no matemáticos, incluido el operador de asignación (=) y operadores binarios. El método más difícil sería escribir un tokenizador para analizar la expresión matemática, porque no es un lenguaje regular.

No dude en intentar y romper el working example que escribí, si puede o si nota un problema, deje un comentario y veré qué puedo hacer para solucionarlo.


Nota: Yi Jiang mencionó in JavaScript chat que también podría ser útil para permitir minúsculas para cosas como Math.PI. Si ese es el caso, sólo podría añadir el else if declaración siguiente en la función de reemplazo:

else if (Math.hasOwnProperty($0.toUpperCase()) 
    return "Math."+$0.toUpperCase(); 

agregarlo entre la declaración if y else (example).

+0

Gran enfoque, me ayudó a resolver un problema similar – odiseo

+3

"El mayor daño que cualquier usuario podía es prácticamente lo que ya podían hacer usando la consola incorporada en cualquiera de los principales navegadores "se basa en premisas falsas. Las cadenas provienen del exterior del navegador a través de servidores y URL. La mejor política es codificar asumiendo que las entradas a su función provendrán de lugares que no espera que otros desarrolladores agreguen a su aplicación, lo que significa que no usará operadores excesivamente poderosos como 'eval'. –

+1

@Mike: me cuesta aceptar el 100%. Si bien lo que dijiste es cierto al evaluar los aportes de otras fuentes, acepto mi respuesta cuando solo estás evaluando la entrada del usuario. –

3

Puede usar el analizador de expresiones avanzadas de math.js, que no utiliza la evaluación de JavaScript.

http://mathjs.org

Uso:

var ans = math.eval('2 * (3 + 4)'); 

o utilizar el analizador (que admite asignaciones de variables y de funciones):

var parser = math.parser(); 
var ans = parser.eval('2 * (3 + 4)'); 
1

Trate nerdamer

var result = nerdamer('sqrt(4)+cos(1)-2').evaluate(); 
 
document.getElementById('text').innerHTML = result.text();
<script src="http://nerdamer.com/js/nerdamer.core.js"></script> 
 
<div id="text"></div>

Cuestiones relacionadas