JSON.parse与eval()


94

我的Spider Sense警告我,使用eval()解析传入的JSON是一个坏主意。我只是想知道JSON.parse()-我假设它是JavaScript的一部分而不是浏览器特定的功能-是否更安全。


在性能方面,至少在V8(Chromium的JS引擎)中JSON.parse比快eval来源
保罗

Answers:


110

如果使用,您将更容易受到攻击eval:JSON是Javascript的子集,而json.parse仅解析JSON,而eval这却为所有JS表达式敞开了大门。


“您更容易受到攻击”,我完全不同意!
Hydroper

4
抱歉,马修斯,我必须同意。问题是当您使用eval()解释“用户输入”时-这是JavaScript外部的任何源(包括从Servlet或您调用的其他Web服务返回的值)。您不能保证用户没有直接将恶意JavaScript输入到客户端应用程序中,也不能保证由于存储在服务器数据库中的数据未经验证然后通过AJAX样式调用传递给您的程序而间接输入了恶意JavaScript。您可能仍需要验证各个字段,以避免“混淆的代理”攻击,但是使用JSON.parse是一个不错的第一步。
杰克·桑顿(JackLThornton)

1
@Hydro概念的简短证明:试试eval('alert(1)');
Valerio Bozz

37

所有JSON.parse实现最有可能使用eval()

JSON.parse基于Douglas Crockford的解决方案,该解决方案eval()497行使用。

// 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 + ')');

的优点JSON.parse是它可以验证参数是否为正确的JSON语法。


56
是的,除了前面的那一行验证它是一个安全有效的字符串。
尼克

6
JSON.parse()在Linux Mint系统上的Firefox 28和Chromium 33中进行了测试。它的速度是eval()Firefox的2倍,而Chromium是4倍。我不确定您要发布的源代码,但是在我的浏览器中它们不是同一回事。
jbo5112

@plodder的“优势”可能不便宜,无法进行验证。
mmm 2015年

2
现代浏览器提供了本机JSON.parse()实现,它比eval()基于解析器的解析器更安全,更快捷。
Mohammad Alhashash

15

并非所有浏览器都具有本机JSON支持,因此有时您需要使用eval() JSON字符串。使用http://json.org中的 JSON解析器,因为它可以为您轻松处理所有事情。

Eval() 是邪恶的,但是对某些浏览器来说却是必然的邪恶,但是在可以避免的地方,请这样做!!!!


12

JSON.parse()和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()时没有歧义。
杰夫·洛里2014年

9

如果您使用解析JSON eval,则将允许解析的字符串包含绝对的任何内容,因此,您可以发现自己正在执行函数调用或其他操作,而不仅仅是一组数据。

此外,JSON的parse接受一个aditional的参数,齐磊,让您指定如何(更多信息和示例在线文档处理某些价值观,如日期时间在这里


4

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


是的,我知道。您是否暗示JSON.parse()仅评估JSON并在所有其他传入数据上失败?还是仅仅是包装:var myObject = eval('('+ responseText +')'); ??
Kevin Major

6
@Kevin Major:是的,本机实现JSON.parse(直接实现到JavaScript引擎中)仅解析JSON。但是其他非本地实现使用一些完整性检查,然后eval出于性能原因使用。
Gumbo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.