1 回答

TA贡献1851条经验 获得超4个赞
所有,我能想到的是将脚本包装在它自己的函数中,就像 nodejs 已经为 commonJS 模块所做的那样。这是常规包装。
(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});
如果您使用自己的包装器包装该用户代码,然后当您调用它来执行它时,您可以为 和任何其他半全局符号定义您自己的require值module。
如果你也把'use strict'; 作为包装函数的第一行(在任何用户代码之前),那么这将消除对global对象的默认分配,x = 4因为如果没有首先明确定义,这将是一个错误x。如果您随后还创建自己的全局对象并将其作为参数传递,则可以防止任何人分配给真正的全局对象。我认为您不能阻止对预先存在的全局变量的隐式读取访问。
因此,您的包装器可能如下所示:
(function(exports, require, module, __filename, __dirname, global) {
'use strict';
// insert user code here before evaluating it with eval()
// and getting the function which you can then call and pass the desired arguments
});
然后,当你调用这个函数时,你把你想要的所有参数的值传递给它(不是真实的)。
请注意,很难说这种方案的防漏性能到底如何。任何真正的安全都应该在资源受限的虚拟机中运行。
另一个想法,您可以在具有自己的原始全局变量集的工作线程中运行。因此,您完成上述所有操作并在工作线程中运行它。
在评论中解决您的问题:
是否“使用严格”;需要进入包装函数内部还是外部?
它必须是包装函数内的第一行代码,就在您插入用户代码的位置之前。这个想法是强制该包装器内的功能范围(用户代码所在的位置)处于严格模式,以限制它可以做的一些事情。
你能解释一下“我认为你不能阻止对预先存在的全局变量的隐式读取访问。”吗?如果我将自己的对象作为全局对象提供,内部脚本如何访问预先存在的全局对象?
global任何代码,甚至是严格模式代码都可以在没有前缀的情况下访问预先存在的全局变量。虽然您可以通过在包装函数参数中使用您自己的遮蔽它global并强制它进入严格模式来阻止代码创建新的全局变量,但您不能阻止严格模式代码读取现有的全局变量,因为它们可以在没有全局前缀的情况下这样做. 因此,如果有一个预先存在的名为“foo”的全局变量,那么现有代码可以像这样引用它:
console.log(foo);
或者
foo = 12;
如果foo在更近的范围内没有,解释器将foo在全局对象上找到并使用它。
请注意,严格模式会阻止自动创建新的全局,例如:
greeting = "happy birthday"
您能否详细说明没有“资源受限的虚拟机”?
我说的是真正的硬件/操作系统级别的虚拟机,它们允许您完全控制进程可能使用的资源(磁盘访问、套接字、内存、硬件等)。它本质上是一个与同一系统上的任何其他 VM 分开的虚拟计算机环境。这是一个更严格的控制水平。
WorkerThread 是一个非常有趣的概念。会看看!我的理解是 WorkerThreads 提供内存隔离,共享数据的唯一方法是发送消息(有效地创建副本)?
是的,工作线程提供了很好的隔离,因为它们启动了一个全新的 JS 引擎并拥有自己的全局变量。它们可以以某种方式共享 ArrayBuffers(如果你选择这样做的话),但是普通的 JS 变量不能跨线程边界访问。它们通常会通过消息传递(通过事件队列自动同步)进行通信,但如果需要,您也可以通过套接字进行通信。
添加回答
举报