Javascript中算术expression式的安全评估

我需要在Javascript中评估用户input的算术expression式,比如“2 *(3 + 4)”,但是我不想为了安全的原因而使用eval

我可以删除所有不是数字或操作符的字符,但是我不确定这是否安全,如果用户可以使用cossqrt等函数,那将会很好。

有没有任何Javascript库进行算术expression式评估?

你可以尝试JavaScript Expression Evaluator :

这个库是Raphael Graf的ActionScript Expression Parser的修改版本。 当我编写JavaScript函数绘图器时,我想要使用JavaScript的eval函数更好的select 。 目前没有安全风险,因为您只能在自己的浏览器中运行代码,但对于math(Math.pow(2 ^ x)而不是2 ^ x等)来说并不方便。

那么你的代码将会是这样的:

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

正如已经提到的,任何用户可以做的最大的损害就是他们已经可以在任何主stream浏览器中使用内置控制台。 但是,如果你想限制用户使用Math属性/方法,你可以写一个简单的正则expression式来为你处理。 像这样的东西应该工作:

 function mathEval (exp) { var reg = /(?:[az$_][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"); }; } 

我意识到你不想使用eval出于安全的原因,但正则expression式应该使它非常安全,因为它排除任何不是Math对象的直接属性和大多数非mathJS运算符的单词,包括赋值运算符( = )和二元运算符。 更难的方法是编写一个标记器来parsingmathexpression式,因为它不是一种常规的语言。

随意尝试打破我写的工作示例 ,如果可以的话,或者如果您发现问题,留下评论,我会看看我能做些什么来解决它。


注意:Yi Jiang 在JavaScript聊天中提到,允许像Math.PI这样的小写字母也是有用的。 如果是这样的话,你可以在replace函数中添加else if语句:

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

ifelse语句之间添加它( 例子 )。

您可以使用math.js中的高级expression式parsing器,它不使用JavaScript的eval。

http://mathjs.org

用法:

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

或者使用parsing器(它支持variables和函数赋值):

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

您可以使用正则expression式来replace除白名单之外的所有内容。 但是由于JavaScript是在客户端上执行的(除非你运行的是AOL http服务器),任何可以修改input的人都可以修改代码 – 所以你并没有真正使它比现在更安全。

尝试nerdamer

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