【问题标题】:Eval is evil... So what should I use instead?eval 是邪恶的……那我应该用什么代替呢?
【发布时间】:2010-10-13 09:27:33
【问题描述】:

一个 ajax 请求返回一个标准 JSON 数组,其中填充了我的用户输入。输入已经过净化,使用 eval() 函数,我可以轻松创建我的 javascript 对象并更新我的页面...

所以这就是问题所在。无论我多么努力地清理输入,我都宁愿不使用 eval() 函数。我已经检查了谷歌的方法来使用“没有 eval 的 AJAX 中的 JSON”并且已经运行了一堆不同的方法......

我应该使用哪一个?是否有一种标准的、经过验证的安全方式来执行此操作?

【问题讨论】:

标签: javascript ajax eval


【解决方案1】:

我想说,一旦输入被净化, eval 是最好的方法。如果您的服务器受到威胁,人们无论如何都可以向客户端发送他们想要的任何脚本。因此,进行评估并不是很大的安全风险。如果您担心人们在数据包到达客户端之前对其进行操作,那么同样可以修改脚本本身。

不用担心评估。但是请确保将其包装在 try...catch 块中,这样如果您的 JSON 被损坏,您的用户就不会收到 JS 错误。

:)

【讨论】:

    【解决方案2】:

    与命令设计模式比较:http://en.wikipedia.org/wiki/Command_pattern。鉴于此,您可以精确定义客户端可以执行的操作,并且您的应用程序将与底层解释一样安全。

    【讨论】:

      【解决方案3】:

      取决于您要通过卫生设施完成什么。 prototype 框架支持 JSON 和安全评估,我取得了巨大的成功。

      【讨论】:

        【解决方案4】:

        json.org 有个不错的javascript library

        简单用法:

        JSON.parse('[{"some":"json"}]');
        JSON.stringify([{some:'json'}]);
        

        编辑:正如 cmets 中所指出的,如果您查看它的源代码,这将使用 eval(尽管它看起来首先要经过清理)

        要完全避免它,请查看 json_parse 或 json-sans-eval

        json2.js 不安全,json_parse.js 很慢,json-sans-eval.js 没有验证

        【讨论】:

        • 它仅使用 eval 作为不支持 JSON 对象的浏览器的后备,如果它没有“解析”功能。
        • json2.js 不安全 从哪里来?它有 1mb 的正则表达式,可以在使用 eval 之前合成字符串
        【解决方案5】:

        是否有标准的、经过验证的安全方式来执行此操作?

        在即将推出的 JavaScript 的 ECMAScript 3.1 版本中提出了一种执行此操作的标准方法:JSON.parse。

        它将在 IE8、Firefox 3.1/3.5 以及很可能在未来的其他流行浏览器中得到支持。同时,您可以回退到或独占使用 eval()。邪恶可能是也可能不是;当然它会比 JSON.parse 慢。但这是当今解析 JSON 的常用方法。

        如果攻击者能够将恶意 JavaScript 注入到您通过 JSON 吐出的内容中,那么您需要担心的问题比 eval-is-evil 更大。

        【解决方案6】:

        为了安全地将 JSON 转换为 JS 对象,您应该使用 JSON 解析器,例如 this library 提供的 JSON.parse() 函数。

        【讨论】:

          【解决方案7】:

          如果您确定没有注入风险,并且您不是 eval()ing 在循环中,请使用 eval()。与其他选项相比,它肯定会更慢,可能会中断,并且需要客户端下载额外的代码。

          【讨论】:

            【解决方案8】:

            从 jQuery 中“窃取”

            // Try to use the native JSON parser first
            return window.JSON && window.JSON.parse ?
                window.JSON.parse( data ) :
                (new Function("return " + data))();
            

            【讨论】:

              【解决方案9】:

              问题: eval 带来的问题是它在全局范围内执行

              eval.call(document, "console.log(this)")
              eval.call(navigator, "console.log(this)")
              eval.call(window, "console.log(this)")
              (function(){eval.call(document, "console.log(this)")})()
              >Window
              

              场景:

              假设您在各种文档元素的标记代码中使用单个属性,例如属性 onvisible

              <img src="" onvisible="src='http://www.example.com/myimg.png';">
              

              您想获取所有具有此属性的元素,将 onvisible-content-string 转换为闭包并将其放入 EventHandler 队列中。这就是 JS Function 构造函数发挥作用的地方。

              Function === 0..constructor.constructor
              >true
              
              Function('return [this, arguments]').call(window, 1,2,3)
              >Window, Arguments[3]]
              Function('return [this, arguments]').call(document, 1,2,3)
              >Document, Arguments[3]]
              Function('return [this, arguments]').call(navigator, 1,2,3)
              >Navigator, Arguments[3]]    
              

              把它们放在一起:

              var eventQueue = [];
              var els = document.querySelectorAll('[onvisible]');
              
              for (var el in els) {
                  var jscode = els[el].getAttribute('onvisible');
                  eventQueue.push( {el:els[el], cb:Function(jscode)} )
              }
              
              //eventQueue[0].cb.call(scope, args);
              

              【讨论】:

                猜你喜欢
                • 2011-02-04
                • 2010-10-31
                • 2011-04-28
                • 2013-08-18
                • 1970-01-01
                • 2012-10-20
                • 2010-09-16
                相关资源
                最近更新 更多