Eval是邪恶的...那么我应该使用什么呢?

时间:2009-03-14 19:55:25

标签: javascript ajax eval

ajax请求返回一个标有我用户输入的JSON数组。输入已经过清理,使用eval()函数,我可以轻松创建我的javascript对象并更新我的页面......

所以这就是问题所在。无论我如何努力消毒输入,我宁愿不使用eval()函数。我已经检查了谷歌使用“没有评估的AJAX中的JSON”的方法,并且运行了很多不同的方法......

我应该使用哪一个?是否有一种标准的,经过验证的安全方法?

9 个答案:

答案 0 :(得分:21)

json.org有一个很好的javascript library

简单用法:

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

编辑:正如评论中所指出的,如果您查看其来源,它会使用eval(尽管它看起来首先要清理)

要完全避免,请查看json_parsejson-sans-eval

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

答案 1 :(得分:11)

  

是否有标准的,经过验证的安全方法?

在即将推出的ECMAScript 3.1版JavaScript中,有一种建议的标准方法:JSON.parse

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

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

答案 2 :(得分:9)

我想说,一旦输入被消毒,eval就是最好的方式。如果您的服务器遭到入侵,人们将无论如何都能够将他们想要的任何脚本发送给客户端。所以放一个评估并不是一个很大的安全风险。如果您担心人们在到达客户端之前操纵数据包,那么可以再次修改脚本本身。

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

:)

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

取决于您在环境卫生方面要做的事情。 prototype框架支持JSON和安全评估,我取得了很大的成功。

答案 6 :(得分:0)

如果您确定没有注射风险,并且您在循环中不是eval()ing,请使用eval()。它将与其他选项相媲美,这些选项肯定会变慢,可能会中断,并且需要客户端下载其他代码。

答案 7 :(得分:0)

来自jQuery的“偷来的”

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

答案 8 :(得分:0)

<强>问题: 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 === 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);