我想知道是否可以在浏览器中运行JavaScript沙箱,以防止访问HTML页面中运行的JavaScript代码通常可用的功能.
例如,假设我想为最终用户提供一个JavaScript API,让他们定义在"有趣事件"发生时运行的事件处理程序,但我不希望这些用户访问该window
对象的属性和功能.我能做到吗?
在最简单的情况下,假设我想阻止用户呼叫alert
.我能想到的几种方法是:
window.alert
全球重新定义.我不认为这是一种有效的方法,因为在页面中运行的其他代码(即用户在其事件处理程序中未编写的内容)可能想要使用alert
.
将事件处理程序代码发送到要处理的服务器.我不确定将代码发送到服务器进行处理是正确的方法,因为事件处理程序需要在页面的上下文中运行.
也许服务器处理用户定义的函数然后生成要在客户端上执行的回调的解决方案可行吗?即使这种方法有效,是否有更好的方法来解决这个问题?
Google Caja是一个源到源的翻译器,"允许您将不受信任的第三方HTML和JavaScript内嵌到您的页面中,并且仍然是安全的."
看看Douglas Crockford的ADsafe:
ADsafe可以将访客代码(例如第三方脚本广告或小部件)放在任何网页上.ADsafe定义了一个强大的JavaScript子集,允许访客代码执行有价值的交互,同时防止恶意或意外损坏或入侵.ADsafe子集可以通过JSLint等工具进行机械验证,因此无需人工检查即可查看访客代码的安全性.ADsafe子集还实施了良好的编码实践,增加了访客代码正确运行的可能性.
您可以通过查看项目的GitHub存储库中的template.html
和template.js
文件来查看如何使用ADsafe的示例.
我创建了一个名为jsandbox的沙盒库,它使用Web worker对沙盒进行评估.它还有一个输入方法,用于显式提供它本来无法获得的沙盒代码数据.
以下是API的示例:
jsandbox .eval({ code : "x=1;Math.round(Math.pow(input, ++x))", input : 36.565010597564445, callback: function(n) { console.log("number: ", n); // number: 1337 } }).eval({ code : "][];.]\\ (*# ($(! ~", onerror: function(ex) { console.log("syntax error: ", ex); // syntax error: [error object] } }).eval({ code : '"foo"+input', input : "bar", callback: function(str) { console.log("string: ", str); // string: foobar } }).eval({ code : "({q:1, w:2})", callback: function(obj) { console.log("object: ", obj); // object: object q=1 w=2 } }).eval({ code : "[1, 2, 3].concat(input)", input : [4, 5, 6], callback: function(arr) { console.log("array: ", arr); // array: [1, 2, 3, 4, 5, 6] } }).eval({ code : "function x(z){this.y=z;};new x(input)", input : 4, callback: function(x) { console.log("new x: ", x); // new x: object y=4 } });
我认为js.js值得一提.它是一个用JavaScript编写的JavaScript解释器.
它比原生JS慢大约200倍,但它的本质使它成为一个完美的沙盒环境.另一个缺点是它的大小 - 几乎600 kb,在某些情况下可能适用于台式机,但不适用于移动设备.
正如其他响应中所提到的,它足以将沙盒iframe中的代码(不将其发送到服务器端)并与消息进行通信.我建议看看我创建的一个小型库,主要是因为需要为不受信任的代码提供一些API,就像问题中所描述的那样:有机会将特定的函数集导出到沙箱中不受信任的代码运行.还有一个演示,它执行用户在沙箱中提交的代码:
http://asvd.github.io/jailed/demos/web/console/