JSON.parse与eval()的区别

102

我的“蜘蛛感”告诉我使用 eval() 解析传入的 JSON 是个坏主意。我只是想知道 JSON.parse() 是否更安全,我认为它是 JavaScript 的一部分而不是特定于浏览器的函数。


就性能而言,在V8(Chromium的JS引擎)中,JSON.parseeval更快。来源 - Paul
6个回答

118

如果使用了eval函数,您更容易受到攻击:JSON是Javascript的一个子集,而json.parse只解析JSON数据,然而使用eval会让所有JS表达式都可以被执行,这就为安全漏洞留下了后门。


7
抱歉,Matheus,我必须同意。问题在于当您使用eval()来解释“用户输入”时-这是从JavaScript外部获取的任何来源(包括从Servlet或其他Web服务返回的值)。您无法保证用户没有直接将恶意JavaScript输入到客户端应用程序中,也无法保证由于未经验证的数据存储在服务器数据库中并通过类似AJAX的调用传递给您的程序而间接导致此类情况发生。您可能仍然需要验证各个字段以避免“混淆代理”攻击,但使用JSON.parse是一个很好的第一步。 - JackLThornton
2
@Hydro 简短的概念证明:尝试 eval('alert(1)'); - Valerio Bozz

42

所有的 JSON.parse 实现很可能都使用了 eval()

JSON.parse 基于Douglas Crockford 的解决方案,其中在第497行使用了 eval()

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

j = eval('(' + text + ')');
< p > JSON.parse 的优点是它会验证参数的正确性,确保符合 JSON 语法。


62
是的,除了在那之前的那一行验证它是一个安全和有效的字符串。 - nickf
8
我在我的Linux Mint系统上测试了Firefox 28和Chromium 33中的JSON.parse(),与eval()相比,在Firefox中快2倍,在Chromium中快4倍。我不确定您发布的源代码是什么,但在我的浏览器中它们并不相同。 - jbo5112
@plodder “优势” 可能不便宜来进行验证。 - mjs
5
现代浏览器提供本地的JSON.parse()实现,比基于eval()的解析器更安全和更快。 - Mohammad Alhashash

15

并非所有浏览器都具备本地 JSON 支持,因此有时需要使用 eval() 来处理 JSON 字符串。使用来自 http://json.org 的 JSON 解析器,它会更轻松地处理所有操作。

eval() 虽然有用,但在某些浏览器上它可能是一种必要的恶魔,但如果能避免使用,就应该避免!!!


现在它已不再正确,即使在之前正确的时候,你也应该使用适当的解析器。 - reducing activity

11

JSON.parse()和eval()在接受内容方面存在差异。请尝试使用eval()来运行以下代码:

var x = "{\"shoppingCartName\":\"shopping_cart:2000\"}"

eval(x)         //won't work
JSON.parse(x)   //does work

请参考这个 示例


1
eval不起作用是因为它将字符串解析为代码语句,因此将"{...}"视为代码表达式而不是值声明表达式。如果消除歧义(例如"[{....}]"),则对表达式的性质毫无疑问,eval将创建一个包含已解析对象的数组。 - Charles HETIER
1
是的。传统上,x会被括号包裹起来:eval("("+x+")")。但我说的仍然成立:使用JSON.parse()时没有歧义。 - Jeff Lowery

9
如果您使用eval解析JSON,那么您允许被解析的字符串包含任何内容,因此它不仅仅是一组数据,而可能会执行函数调用或其他操作。
此外,JSON的parse接受一个额外的参数reviver,它允许您指定如何处理某些值,例如日期时间(有关更多信息和示例,请参见内联文档here)。

4

JSON只是JavaScript的一个子集。但是eval评估的是完整的JavaScript语言,而不仅仅是JSON的子集。


我明白了。你是在暗示JSON.parse()只能解析JSON格式的数据,对于其他类型的输入数据则会失败吗?还是说它只是一个对下述代码的封装:var myObject = eval('(' + responseText + ')');? - Kevin Major
7
是的,原生实现的 JSON.parse (直接实现在 JavaScript 引擎中)只解析 JSON。但是其他非原生实现会进行一些合理性检查,然后出于性能原因使用 eval - Gumbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接