Javascript 中算术表达式的安全评估

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5066824/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 15:49:55  来源:igfitidea点击:

Safe evaluation of arithmetic expressions in Javascript

javascriptparsingmath

提问by Giuseppe Ottaviano

I need to evaluate user-entered arithmetic expressions like "2 * (3 + 4)" in Javascript but I don't want to use evalfor security reasons.

我需要在 Javascript 中评估用户输入的算术表达式,如“2 * (3 + 4)”,但eval出于安全原因我不想使用。

I could strip out all the characters that are not numbers or operators but I'm not sure this would be safe anyway and it would be nice if the user could use functions like cos, sqrt, etc...

我可以去掉所有的不是数字或运营商的角色,但我不知道这将是安全的反正这将是很好,如果用户可以使用类似的功能cossqrt等...

Are there any Javascript libraries that do arithmetic expression evaluation?

是否有任何 Javascript 库可以进行算术表达式评估?

回答by Maxym

you can try JavaScript Expression Evaluator:

你可以试试JavaScript 表达式评估器

This library is a modified version of Raphael Graf's ActionScript Expression Parser. When I wrote the JavaScript Function Plotter, I wanted a better alternative to using JavaScript's eval function. There's no security risk currently, because you can only run code in your own browser, but it's not as convenient for math (Math.pow(2^x) instead of 2^x, etc.).

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

then your code will be like that:

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

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

回答by Andy E

As already mentioned, the most damage any user could do is pretty much what they could already do using the built-in console in any of the major browsers. However, if you wanted to restrict the user to using Mathproperties/methods, you could write a simple regex to handle this for you. Something like this should work:

如前所述,任何用户可能造成的最大损害几乎是他们在任何主要浏览器中使用内置控制台已经可以做到的。但是,如果您想限制用户使用Math属性/方法,您可以编写一个简单的正则表达式来为您处理。这样的事情应该工作:

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 (
else if (Math.hasOwnProperty(
var ans = math.eval('2 * (3 + 4)');
.toUpperCase()) return "Math."+
var parser = math.parser();
var ans = parser.eval('2 * (3 + 4)');
.toUpperCase();
) { // If the name is a direct member of Math, allow if (Math.hasOwnProperty(
var result = nerdamer('sqrt(4)+cos(1)-2').evaluate();
document.getElementById('text').innerHTML = result.text();
)) return "Math."+
<script src="http://nerdamer.com/js/nerdamer.core.js"></script>
<div id="text"></div>
; // 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"); }; }

I realize you didn't want to use evalfor security reasons, but the regex should make it pretty safe as it rules out any words that aren't directproperties of the Mathobject and most non-math JS operators, including the assignment operator (=) and binary operators. The harder method would be writing a tokenizer to parse the mathematical expression, because it's not a regular language.

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

Feel free to try and break the working exampleI wrote, if you can or if you notice a problem, leave a comment and I'll see what I can do to fix it.

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



注:易江提到 in JavaScript chat在 JavaScript 聊天中,允许像Math.PIMath.PI. 如果是这种情况,您可以else ifelse if在替换函数中添加以下语句:

##代码##

Add it between the ifand elsestatement (example).

ifandelse语句之间添加它(示例)。

回答by Jos de Jong

You can use the advanced expression parser from math.js, which does not use JavaScript's eval.

您可以使用 math.js 中的高级表达式解析器,它不使用 JavaScript 的 eval。

http://mathjs.org

http://mathjs.org

Usage:

用法:

##代码##

or use the parser (which supports variable and function assignments):

或使用解析器(支持变量和函数赋值):

##代码##

回答by ArchHaskeller

Try nerdamer

试试书呆子

##代码## ##代码##

回答by symcbean

You could use a regex to replace everything except for your whitelist. But since the javascript is executed on the client (unless you're running the AOL http server) anyone who can modify the inputs can modify the code as well - so you're not really making it anymore or less secure than it already is.

您可以使用正则表达式替换除白名单之外的所有内容。但由于JavaScript是在客户端上执行的(除非你正在运行的AOL http服务器)人谁可以修改输入可以修改代码,以及-所以你没有真正使其成为任何或多或少的安全比它已经是.