如何避免在用户定义的函数中使用 JavaScript eval()

How to avoid using JavaScript eval() in user-defined function

我正在尝试制作一个通用的 table-top RPG helper web 应用程序。它必须是通用的,因为海岸奇才非常保护他们的版权。因此,为了避免停止和停止,系统必须能够加载任意规则。也就是说,我和我的伙伴(以及大多数其他用户)将在 D&D 中使用它。

在 D&D 中,修饰符基于角色的统计数据。要获得修正值,您需要统计数据,减去 10,除以 2,然后向下舍入。

function getModifier(statValue) {
    return Math.floor((statValue - 10) / 2);
}

我的应用程序将能够从 .json 文件加载游戏规则。我希望能够使这个修饰函数成为用户可定义的。最简单的方法是 eval() 他们在 .json 文件中提供的任何内容,但显然由于安全问题,这是一个糟糕的主意。

不幸的是,我想不出一个简单的方法来安全地解决这个问题。显然我可以编写自己的解析器,但这比我 like/am 目前能够做到的要复杂。

想法?

您的问题的一个解决方案是使用 sandboxed iframes (current supported by all major browsers

您 运行 在单独的页面上使用有限权限的用户代码,这样代码就不会干扰应用程序的其余部分。您可以使用 postMessage()window.onmessage.

与沙盒页面通信

首先,请记住,这都是在客户端进行的。只要您信任 JSON(它来自您的服务器或与应用程序本身一起控制),您就可以使用它。这并不能完全排除一些木马插入恶意规则,但我认为僵尸网络还没有学会玩 D&D。

从字面上 避免 eval 并提供一些安全性,您可以使用 new Function。它采用参数名称列表,后跟函数主体,使您可以对函数的定义方式以及从何处引用函数进行大量控制。您只需要将正文存储在 JSON 文件中,使您可以在很大程度上控制参数并使其难以分配到全局范围,从而最大限度地减少攻击面(例如它)。

如果你想玩得开心,现在你的规则主要是数学的,你可以考虑使用像pegjs to generate a parser for your rules. Calculators are one of the classic introductions to parsers and compilers, so this could be an opportunity to play with some fun tech. The rules and parsers built by pegjs are very easy to use in a JS project (I have an example using PegJS and ES6 via Babel)这样的工具。

我认为有两种选择。第一,如果你 100% 想在 .json 中定义函数,你将需要解析。 JSON 不允许函数,因此您需要将函数存储为字符串并对其求值。

更好的方法是同时提供 config.js 能力。也许 .json 会有一个 "configUrl": 属性,然后公开众所周知的 API,例如,您可以从 config.js 文件中调用的 RPGHelper.setModifer(someFunction)。然后用户可以在那里自由定义任何任意逻辑。

我快速 google 搜索并找到了两个选项 - http://mathjs.org and http://jsep.from.so

顺便说一句。编写自己的解析器并不难。您也许可以用不到 100 行代码编写一个足以满足您的目的的代码