是否可以限制javascript函数的范围?

cam*_*mil 24 javascript security

假设我在全局范围内有变量.

假设我希望定义一个我可以保证不能访问这个变量的函数,有没有办法包装函数,或调用函数,这将确保这个?

实际上,我需要任何规定的函数来对变量进行良好定义的访问,并且该访问要在该函数定义之前定义,并与该函数定义分开.

动机:我正在考虑用户提交功能的可能性.我应该能够相信这个功能是各种各样的"安全",因此很乐意在我自己的网站上发布它们.

jos*_*736 18

iframe托管在不同Origin上运行代码.这是保证不受信任的代码被沙箱化并阻止访问全局变量或页面DOM 的唯一方法.


Jul*_*ire 10

使用嵌入式Web Workers可以允许运行安全功能.这样的东西允许用户输入javascript,运行它并获得结果而无需访问您的全局上下文.

globalVariable = "I'm global";

document.getElementById('submit').onclick = function() {
  createWorker();
}


function createWorker() {
  // The text in the textarea is the function you want to run
  var fnText = document.getElementById('fnText').value;

  // You wrap the function to add a postMessage 
  // with the function result
  var workerTemplate = "\
function userDefined(){" + fnText +
    "}\
postMessage(userDefined());\
onmessage = function(e){console.log(e);\
}"

  // web workers are normally js files, but using blobs
  // you can create them with strings.
  var blob = new Blob([workerTemplate], {
    type: "text/javascript"
  });

  var wk = new Worker(window.URL.createObjectURL(blob));
  wk.onmessage = function(e) {
    // you listen for the return. 
    console.log('Function result:', e.data);
  }

}
Run Code Online (Sandbox Code Playgroud)
<div>Enter a javascript function and click submit</div>
<textarea id="fnText"></textarea>
<button id="submit">
  Run the function
</button>
Run Code Online (Sandbox Code Playgroud)

您可以尝试这些,例如通过在textarea中粘贴它:

return "I'm a safe function";
Run Code Online (Sandbox Code Playgroud)

你可以看到它是安全的:

return globalVariable;
Run Code Online (Sandbox Code Playgroud)

你甚至可以拥有更复杂的脚本,如下所示:

var a = 4, b = 5;
function insideFn(){
    // here c is global, but only in the worker context
    c = a + b;
}
insideFn();
return c;
Run Code Online (Sandbox Code Playgroud)

请在此处查看有关Webworkers的信息,尤其是嵌入式Web工作者:https: //developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Embedded_workers


小智 5

有点晚了,但也许会对你有所帮助

function RestrictFunction(params) {

    params = ( params == undefined ? {} : params );
    var scope = ( params.scope == undefined ? window : params.scope );
    var data = ( params.data == undefined ? {} : params.data );
    var script = ( params.script == undefined ? '' : params.script );
    if (typeof params.script == 'function') {
        script = params.script.toString();
        script = script.substring(script.indexOf("{") + 1, script.lastIndexOf("}"));
        }

    // example: override native functions that on the white list

    var setTimeout = function(_function,_interval) {

        // this is important to prevent the user using `this` in the function and access the DOM
        var interval = scope.setTimeout( function() { 
            RestrictFunction({
                scope:scope,
                data:data,
                script:_function
                });
            } , _interval );

        // Auto clear long user intervals
        scope.setTimeout( function() {
            scope.clearTimeout(interval);
            } , 60*1000 );

        return interval;
        }       

    // example: create custom functions

    var trace = function(str) {
        scope.console.log(str);
        }   

    return (function() {

        // remove functions, objects and variables from scope

        var queue = [];
        var WhiteList = [
            "Blob","Boolean","Date","String","Number","Object","Array","Text","Function",
            "unescape","escape","encodeURI","encodeURIComponent","parseFloat","parseInt",
            "isNaN","isFinite","undefined","NaN",
            "JSON","Math","RegExp",
            "clearTimeout","setTimeout"
            ];

        var properties = Object.getOwnPropertyNames(scope);
        for (var k = 0; k<properties.length; k++ ) {
            if (WhiteList.indexOf(properties[k])!=-1) continue;
            queue.push("var "+properties[k]+" = undefined;");
            }   

        for (var k in scope) {
            if (WhiteList.indexOf(k)!=-1) continue;
            queue.push("var "+k+" = undefined;");
            }

        queue.push("var WhiteList = undefined;");   
        queue.push("var params = undefined;")   ;
        queue.push("var scope = undefined;")    ;
        queue.push("var data = undefined;") ;
        queue.push("var k = undefined;");   
        queue.push("var properties = undefined;");  
        queue.push("var queue = undefined;");   
        queue.push("var script = undefined;");  
        queue.push(script); 

        try {
        return eval( '(function(){'+ queue.join("\n") +'}).apply(data);' ); 
        } catch(err) { }

        }).apply(data);

    }   
Run Code Online (Sandbox Code Playgroud)

使用示例

// dummy to test if we can access the DOM
var dummy = function() {

    this.notify = function(msg) {
        console.log( msg );
        };

    }

var result = RestrictFunction({

    // Custom data to pass to the user script , Accessible via `this`
    data:{
        prop1: 'hello world',
        prop2: ["hello","world"],
        prop3: new dummy()
        },

    // User custom script as string or function
    script:function() {

        trace( this );

        this.msg = "hello world";
        this.prop3.notify(this.msg);

        setTimeout( function() {
            trace(this); 
            } , 10 );

        trace( data );
        trace( params );
        trace( scope );
        trace( window );
        trace( XMLHttpRequest );
        trace( eval );

        return "done!"; // not required to return value...

        },

    }); 

console.log( "result:" , result );
Run Code Online (Sandbox Code Playgroud)

  • 这不是傻瓜证明。“跟踪((函数(){返回此}()));” 仍然会显示对全局范围的访问(还有其他方式)。 (2认同)