11

我可以将字符串生成的函数(使用 Function 构造函数)的访问限制为父/全局范围吗?

例如:以下代码原样打印false,因为该函数正在窗口中存储/修改变量 a 。

window.a = 4;
Function("a=3;")()
console.log(a === 4);

我可以限制对窗口/父范围的访问并使其打印出“true”吗?

4

4 回答 4

13

这是一个额外的想法,与 Esailija 的提议一起可能非常强大(请参阅关于他的回答的评论以供讨论)。

您可以创建虚拟 iframe 并使用其Function功能。默认情况下,使用它创建的函数只能访问 iframe 的范围,尽管它仍然可以突破它。幸运的是,按照 Esailija 的建议,很容易防止这种情况发生。

我可以想象这个功能是这样的:

function sandboxed(code) {
    var frame = document.createElement('iframe');
    document.body.appendChild(frame);

    var F = frame.contentWindow.Function,
        args = Object.keys(frame.contentWindow).join();

    document.body.removeChild(frame);

    return F(args, code)();
}

演示

或者,您可能希望'use strict';在代码前添加。


这至少在 Chrome 中有效。以这种方式创建的函数是否可以访问 iframe 的全局范围或页面的全局范围,可以通过以下方式轻松测试:

(function() {
    var frame = document.createElement('iframe');
    document.body.appendChild(frame);
    var same = window === frame.contentWindow.Function('return window;')();
    alert(same ? ':(' : ':)');
    document.body.removeChild(frame);
}());
于 2012-08-08T17:40:21.107 回答
6

我不这么认为。您可以在参数中命名要保护的全局变量,以便它们隐藏它们:

window.a = 4;
Function("a", "a=3;")()
console.log(a === 4);

但是无论您尝试什么,该函数都可以访问全局……这就是为什么它被称为全局。

根据您要执行的操作,还有其他解决方法,例如网络工作者……以及一如既往的隐藏 iframe hacks

于 2012-08-08T17:11:14.387 回答
2

@Esailija 的回答是正确的。此外,我建议首先限制您必须保护的全局变量的数量。将通常放在全局命名空间中的任何内容放在APP您控制的范围内:

var APP = (function() {
    return {
        a: 4
    };
}());

没有办法完全限制对全局范围的访问,但至少这样你只需要保护一个对象:APP.

于 2012-08-08T17:19:22.917 回答
1

这是我改编的sandboxed功能。它接受代码和带有函数参数的可选字典。

function sandboxed(code, args = {}) {
    var frame = document.createElement('iframe');
    document.body.appendChild(frame);
    var F = frame.contentWindow.Function;
    document.body.removeChild(frame);
    return F(...Object.keys(args), "'use strict';" + code)(...Object.values(args));
}

console.log(sandboxed('return a - 10;', {'a': 34}));

// 24
于 2021-02-21T10:05:18.640 回答