猿问

JavaScript 中的动态公式求值:eval() 或 not eval()

我正在开发一个 Web 应用程序,管理员可以在其中定义和调整需要根据最终用户提供的输入值(数字)进行评估的公式。


为了清楚起见,以下是我要排除的简化示例:


const obj = {

    type: "External wall in contact with the ground",

    layer: {

        base: {

            type: "Reinforced concrete (reinforcement 5 vol.%)",

            thickness: 100,                         // <-- user value

            lambda: 2.3,                            // <-- user value

            _r: "{{thickness}}/{{lambda}}/1000",    // <-- admin defined

            r: 0

        },

        waterproofing: {

            type: "Bitumen sheets (single layer)",

            share: 1,           // <-- user value

            _r: "{{share}}",    // <-- admin defined

            r: 0,

        },

        insulation: {

            type: "XPS",

            thickness: 100,                                 // <-- user value

            share: 1,                                       // <-- user value

            lambda: 0.040,                                  // <-- user value

            _r: "{{thickness}}*{{share}}/{{lambda}}/1000",  // <-- admin defined

            r: 0

        }

    }

}


Object.entries(obj.layer).forEach(([key, object]) => {

    var formula = object._r

    Object.keys(object).forEach(k =>

        formula = formula.replace(`{{${k}}}`, object[k])

    )


    obj.layer[key].r = eval(formula)

})


console.log(obj)

这_r是管理员定义的公式。这些{{value}}是最终用户提供的值。


该循环遍历obj.layer属性来评估公式并将答案保存在 中r。


结果将是这个对象:


{

  type: 'External wall in contact with the ground',

  layer: {

    base: {

      type: 'Reinforced concrete (reinforcement 5 vol.%)',

      thickness: 100,

      lambda: 2.3,

      _r: '{{thickness}}/{{lambda}}/1000',

      r: 0.043478260869565216

    },

    waterproofing: {

      type: 'Bitumen sheets (single layer)',

      share: 1,

      _r: '{{share}}',

      r: 1

    },


让我们跳过我不验证对象结构并确保所有值都可用的事实。

我知道eval()这被认为是“危险的”。一个不太好的选择是Function()。然而,并不完美。

到目前为止,我看到了 3 种可能性:

  1. 只有管理员可以更改公式。因此,执行恶意代码的风险非常低。我需要的是验证/清理这些值(类似isFloat()),仅此而已。

  2. 使用该mathjs库,它提供了一个很好的evaluate()功能:



冉冉说
浏览 77回答 1
1回答

繁华开满天机

进一步阅读该主题,mathjs似乎是最合理的解决方案:第三方管理员可能是唯一可以编辑代码的人,但它实际上将在哪里运行?在你的后台?在访客的计算机上?我强烈建议您避免使用 eval(),以免您因任何比特币矿工访问者最终从您的应用程序中签约而受到指责。考虑到这一点,我认为你的第二个选择是正确的。我认为根据一组预定义变量来评估公式是足够安全的。看起来 mathjs 积极避免 eval(): https://github.com/josdejong/mathjs/blob/master/docs/expressions/security.md
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答