想象一个网站,用户可以在其中通过js生成内容。 例如。
用户点击按钮
它请求我们的api(而不是用户的api)
Api返回具有特定字段的对象。
我们显示select
,其中包含用户定义的选项,这些选项是由用户代码或基于我们发送的数据得出的一些计算结果生成的。
这个想法是让用户能够编辑可见的内容(使用我们的结构,我们事先知道返回对象中的哪些字段在做什么)。
第一个解决方案在5分钟内“开发完成”。
用户点击按钮
它将所有必需的数据作为context
发送到我们的api。
我们从数据库用户定义的代码中获取
// here is the code which we write (not user) and we know this code is safe
const APP_CONTEXT = parseInput(); // this can be parameters from command line
const ourLibrary = require('ourLibrary');
// APP_CONTEXT is variable which contains data from frontend. We control data inside APP_CONTEXT, user can not write to it
// here is user defined code
const someVar = APP_CONTEXT['fieldDescribedInOurDocumentation'];
const anotherVar = APP_CONTEXT['anotherFieldFromDocumentation'];
ourLibrary.sendToFrontend(someVar + anotherVar);
在这个非常简单的示例中,一旦用户单击按钮,我们就向api发送了api请求,用户代码已执行,我们将显示执行结果。 ourLibrary
抽象了处理的完成方式。
我认为主要的问题是安全性。我考虑使用受限的nodejs流程。没有网络访问,没有文件系统访问。
是否可以在nodejs进程中拒绝任何导入/要求?我只想让用户只调用所有内置的js函数(Math.min,Math.max,新的Date(),+,-),声明函数等等。因此,它将像复杂的计算器一样工作。而且我们还应该有能力将其发送回前端。例如,通过rabbitmq + nodejs + websockets。如果前者是问题,我们可以使用简单的console.log
。
使用nodejs解释器的一些可能的解决方案(当然不是安全的)。每次需要采取措施时,我们都会执行解释器。
const APP_CONTEXT = parseInput();
const ourLibrary = require('ourLibrary');
const usersCode = getUsersCode();
eval(usersCode);
内部用户代码,他们使用ourLibrary.sendToFrontend
来产生结果。但是此解决方案允许用户使用任何内置的nodejs函数,例如const fs = require('fs')
。当然,使用Linux系统(selinux或类似系统)将限制访问,但是我可以配置/设置nodejs以使其作为简单的js解释器运行吗?可能存在其他可以安全使用的js解释器?安全手段:仅算术,日期函数,数学函数等。没有文件系统访问,没有网络访问。