[英]How to avoid using JavaScript eval() in user-defined function
I'm trying to make a generic table-top RPG helper web app. 我正在尝试制作一个通用的桌面RPG助手Web应用程序。 It has to be generic because Wizards of the Coast is very protective of their copyrights.
它必须是通用的,因为“海岸奇才”非常保护其版权。 So, in order to avoid cease-and-desists, the system has to be capable of loading arbitrary rules.
因此,为了避免停下来,该系统必须能够加载任意规则。 That said, my buddies and I (along with most any other user) will be using it for D&D.
就是说,我和我的好友(以及大多数其他用户)将使用它进行D&D。
In D&D, modifiers are based on a character's stats. 在D&D中,修饰符基于角色的属性。 To get a modifier, you take the stat, subtract 10, divide by 2, and round down.
要获取修饰符,您需要获取统计信息,然后减去10,除以2,然后四舍五入。
function getModifier(statValue) {
return Math.floor((statValue - 10) / 2);
}
My app will be capable to loading a game's rules from a .json file. 我的应用程序将能够从.json文件加载游戏规则。 I want to be able to make this modifier function user-definable.
我希望能够使此修饰符功能可由用户定义。 The easiest way would be to just
eval()
whatever they provide in the .json file, but obviously that's a terrible idea due to security issues. 最简单的方法是仅对.json文件中提供的内容进行
eval()
,但是由于安全问题,显然这是一个糟糕的主意。
Unfortunately, I can't think of a simple way to get around this in a secure manner. 不幸的是,我想不出一种简单的方法来以安全的方式解决这个问题。 Obviously I could write my own parser, but that's more complicated than I'd like/am currently capable of.
显然,我可以编写自己的解析器,但这要比我目前想要的更加复杂。
Ideas? 有想法吗?
First, bear in mind that this is all on the client-side. 首先,请记住,这一切都在客户端。 So long as you trust the JSON (it came from your server or it is controlled alongside the application itself), then you can use it.
只要您信任JSON(它来自服务器或与应用程序本身一起受控制),就可以使用它。 That doesn't completely rule out some trojan inserting malicious rules, but I don't think botnets have learned to play D&D yet.
这并不能完全排除某些木马程序插入恶意规则,但是我认为僵尸网络还没有学会玩D&D。
To literally avoid eval and provide some modicum of security, you can use new Function
. 为了从字面上避免评估并提供某种程度的安全性,可以使用
new Function
。 It takes a list of argument names followed by the function body, allowing you a large amount of control over how the function is defined and where it can be referenced from. 它采用参数名称列表,然后是函数主体,使您可以大量控制函数的定义方式以及可以从何处引用函数。 You only need to store the body in the JSON file, allowing you to largely control the parameters and make it difficult to assign to the global scope, minimizing your attack surface (such as it is) quite a lot.
您只需要将主体存储在JSON文件中,就可以在很大程度上控制参数并使其难以分配给全局范围,从而极大地减少了攻击面。
If you want to have fun with this and now your rules will largely be mathematical, you may consider using a tool like pegjs to generate a parser for your rules. 如果您希望以此为乐 ,现在您的规则基本上是数学的,则可以考虑使用诸如pegjs之类的工具来为规则生成解析器。 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 ).
由pegjs构建的规则和解析器在JS项目中非常易于使用(我有一个通过Babel使用PegJS和ES6的示例 )。
I did a quick google search and found two options - http://mathjs.org and http://jsep.from.so 我做了一个快速的谷歌搜索,发现了两个选择-http : //mathjs.org和http://jsep.from.so
btw. 顺便说一句 writing your own parser is not that difficult.
编写自己的解析器并不困难。 You may be able to write one that's sufficient for your purpose in less than 100 lines of code
您也许可以用不到100行的代码编写一个足以满足您的目的的代码
One solution to your problem is to use sandboxed iframes (current supported by all major browsers 解决您的问题的一种方法是使用沙盒iframe ( 所有主要浏览器均支持该功能)
You run user code on a separate page, with limited priviliges, in such a way that the code does not interfere with the rest of the application. 您可以在权限有限的单独页面上运行用户代码,以使代码不会干扰应用程序的其余部分。 You can communicate with the sandboxed page using
postMessage()
and window.onmessage
. 您可以使用
postMessage()
和window.onmessage
与沙盒页面进行通信。
There are two options as I see it. 我看到有两个选择。 One, if you 100% want to define the function in .json, you will need to parse.
第一,如果您100%想在.json中定义函数,则需要进行解析。 JSON does not allow functions, so you need to store the function as a string and eval it.
JSON不允许使用函数,因此您需要将函数存储为字符串并进行评估。
The better way would be to also provide a config.js ability. 更好的方法是还提供config.js功能。 Perhaps the
.json
would have a "configUrl":
property, and then expose well known apis, eg RPGHelper.setModifer(someFunction)
that you can call from inside the config.js file. 也许
.json
将有一个"configUrl":
属性,然后暴露众所周知的API,如RPGHelper.setModifer(someFunction)
您可以从config.js文件内调用。 The user is then free to define whatever arbitrary logic there. 然后,用户可以自由定义那里的任意逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.