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

Giu*_*ano 13 javascript math parsing

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

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

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

Max*_*xym 20

你可以试试JavaScript Expression Evaluator:

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

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

console.info ( Parser.evaluate( "2 * (3 + 4)" ) ); //prints 14
Run Code Online (Sandbox Code Playgroud)


And*_*y E 10

如前所述,任何用户可以做的最大损害就是他们在任何主流浏览器中使用内置控制台已经可以做的事情.但是,如果您想限制用户使用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 ($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"); };
}
Run Code Online (Sandbox Code Playgroud)

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

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


注意:易江在JavaScript聊天中提到,允许小写等内容也可能有用Math.PI.如果是这种情况,您可以else if在替换函数中添加以下语句:

else if (Math.hasOwnProperty($0.toUpperCase())
    return "Math."+$0.toUpperCase();
Run Code Online (Sandbox Code Playgroud)

ifelse语句(示例)之间添加它.

  • "任何用户可以做的最大的损害就是他们在任何一个主流浏览器中使用内置控制台已经可以做的事情"基于错误的前提.字符串来自浏览器外部的服务器和URL.最好的策略是编写代码,假设您的函数的输入将来自您不希望的地方,因为其他开发人员添加到您的应用程序,这意味着不使用像'eval`这样过于强大的运算符. (4认同)

Jos*_*ong 5

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

http://mathjs.org

用法:

var ans = math.evaluate('2 * (3 + 4)');
Run Code Online (Sandbox Code Playgroud)

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

var parser = math.parser();
var ans = parser.evaluate('2 * (3 + 4)');
Run Code Online (Sandbox Code Playgroud)