JavaScript: 代码注入

@ 2010-12-03 14:18:40
标签:

    代码注入,主要是用来动态加载代码或执行代码。比如处理从server端返回的JSON代码;又比如加载一段JavaScript代码。

    下面讨论解决问题的几种可能方案。

    eval

    • eval 用于执行JavaScript代码
    • window.eval 在Firefox和Chrome中存在,与 eval类似,但在全局空间执行代码。

    下面的例子用来说明 eval和window.eval的区别。

    var v=0;
    function f_a() { eval("var v=5;"); }
    function f_b() { window.eval("var v=5;"); }
    
    f_a(); alert(v); // v = 0
    f_b(); alert(v); // v = 5
    

    script 标签

    可以通过在DOM中添加script节点来执行JavaScript代码。

    function eval_script_src(url){
      var script = document.createElement('script');
      script.setAttribute("type", "application/javascript");
      script.setAttribute("src", url);
      document.head.appendChild(script);  
      //document.head.removeChild(script);  
    }         
    
    function eval_script_text(code){
      var script = document.createElement('script');
      script.setAttribute("type", "application/javascript");
      script.text = code;
      document.head.appendChild(script);  
      //document.head.removeChild(script);  
    }             
    

    这个放法可以用来加载第三方站点的JavaScript脚本。

    execScript

    • execScript 只存在于IE中,作用类似于 window.eval

    关于代码注入的测试

    下面的代码可以用于测试各种代码注入方法在不同浏览器中的行为。

    <textarea id="log" style="width:100%;height:100%;">
    </textarea>
    
    <script type="text/javascript"> 
    function log(txt){
        document.getElementById('log').value += "\n"+txt;
    }
    
    function eval_inside(code){
        eval(code);
    }
    
    function eval_inside_window(code){
        window.eval(code);
    }
    
    function eval_inside_call(code){
        eval.call(window,code);
    }
    
    function eval_inside_execScript(code){
        try{
    	window.execScript(code);
        }catch(e){
        }
    }
    
    function eval_inside_timeout(code){
        code = "eval('"+code.replace(/'/g,'"')+"')";
        setTimeout(code,0);
    }
    
    function eval_script_src(code){
      var script = document.createElement('script');
      script.setAttribute("type", "application/javascript");
      script.setAttribute("src", "data:,"+escape(code));
      document.head.appendChild(script);  
      //document.head.removeChild(script);  
    }
    
    function eval_script_text(code){
      var script = document.createElement('script');
      script.setAttribute("type", "application/javascript");
      script.text = code;
      document.head.appendChild(script);  
      //document.head.removeChild(script);  
    }
    
    var code = 'var v_$n=5;t_$n=4;function f_$n(s){log("... f_$n: v_$n="+v_$n+" , t_$n="+t_$n + "   " + s);}'
             + 'f_$n("(inside)");'
            ;
    	var code2 = 'try{f_$n("(outside)");}catch(e){} try{log(" result: v_$n="+v_$n+" , t_$n="+t_$n);}catch(e){}';
    
    function test_js(n,test_name, func_name){
        var txt = code.replace(/\$n/g, n);
        log('');
        log('*** '+test_name+' ***');
        func_name(txt);
    }
    
    var n = 0;
    n++;
    test_js(n, "eval", eval);
    eval(code2.replace(/\$n/g, n));
    
    n++;
    test_js(n, "eval inside", eval_inside);
    eval(code2.replace(/\$n/g, n));
    
    n++;
    test_js(n, "window.eval", eval_inside_window);
    eval(code2.replace(/\$n/g, n));
    
    n++;
    test_js(n, "eval.call", eval_inside_call);
    eval(code2.replace(/\$n/g, n));
    
    n++;
    test_js(n, "window.execScript", eval_inside_execScript);
    eval(code2.replace(/\$n/g, n));
    
    n++;
    test_js(n, "script.src", eval_script_src);
    eval(code2.replace(/\$n/g, n));
    
    n++;
    test_js(n, "script.text", eval_script_text);
    eval(code2.replace(/\$n/g, n));
    
    n++;
    test_js(n, "setTimeout", eval_inside_timeout);
    eval(code2.replace(/\$n/g, n));    
    </script> 
    
    标签:

      分享到:
      comments powered by Disqus

      22/25ms