使用JavaScript eval解析JSON

7
问题:我正在使用eval解析WebMethods返回的JSON值。

我不想添加jquery-json,因为传输量已经很大了。 所以我用eval解析JSON返回值。
现在有谣言说这是不安全的。为什么?

除非他们黑掉我的服务器,否则没有人可以修改JSOn返回值,在这种情况下,我将面临更大的问题。

如果他们在本地执行此操作,JavaScript只会在他们的浏览器中执行。
因此,我无法看到问题所在。

是否有人能够使用这个具体例子来阐明一下?


function OnWebMethodSucceeded(JSONstrWebMethodReturnValue) 
{
    var result=eval('(' + JSONstrWebMethodReturnValue + ')')
    ... // Adding result.xy to a table
}
2个回答

14

根本问题在于eval可以运行任何JavaScript代码,而不仅仅是反序列化JSON格式数据。当从不受信任或半受信任的源处理JSON时使用它就存在风险。将JSON用括号包裹的常见技巧并不能确保不会执行任意JavaScript代码。考虑这个看似"JSON"但实际上不是的例子:

function(){alert('Hi')})(
如果你有一个变量 x 并执行了以下操作:
var result = eval("(" + x + ")");

...你会看到一个警报--JavaScript已运行。存在安全问题。

如果你的数据来自一个可信任的来源(而且听起来是这样),那么我不会太担心它。不过,您可能会对Crockford在这里的讨论感兴趣(Crockford是JSON的发明者和一位广受尊敬的JavaScript专家)。Crockford还在此页面上提供了至少三个公共领域解析器供您考虑使用:他的json2.js解析器和字符串化器,最小化后只有2.5k大小,但仍然使用eval(它只是先采取了几项预防措施);他的json_parse.js,是一种不使用eval的递归下降解析器;以及他的json_parse_state.js,是一种状态机解析器(同样不使用eval)。因此,您可以选择您喜欢的毒药。(向Camilo Martin致敬,因为他指出了后两个替代方案。)


4
需要注意的是,Crockford 的 JSON 包括另外两个库(除了主要的 json.js 和 json2.js),它们具有不同的解析模式,不使用 eval。它们分别是 json_parse.jsjson_parse_state.js,可以在 这里 找到。 - Camilo Martin
当我没有来自外部源的输入时,可以安全地使用 eval 吗? - Royi Namir
@RoyiNamir:如果您控制进入eval的字符串,并且该字符串将是JSON(或类似JSON),则您至少避免了eval的两个主要“罪恶”(它运行代码并且可能对调用它的范围产生奇怪的影响)。您仍然会启动完整的JavaScript解析器,但就我而言,我并不认为这有什么问题。 - T.J. Crowder

4

越来越多的现代浏览器本地支持JSON解析和编码,这使得您的应用程序可以安全地使用JSON功能而无需加载额外的库。[wikipedia reference]

您可以通过执行以下操作来测试本地JSON支持:

var native_JSON_exists = typeof window.JSON === 'object';

你应该加载一个JSON解析库,比如Douglas Crockford的(由上面的T.J. Crowder提供链接),或者使用框架中提供的功能来处理那些不支持原生JSON的浏览器。(但是在支持原生JSON的浏览器中,至少要使用原生JSON来保护那些幸运拥有现代浏览器的用户)请记住,JSON是JavaScript语法的子集,因此在JavaScript eval语句中有效的字符串可能无法在正确的JSON解析中工作。您可以使用JSLint(http://www.jslint.com/)测试JSON字符串是否存在错误。

1
+1 不幸的是,原生支持还没有准备好进入主流时间;有太多的实现错误(令人惊讶)。但它会到达那里的。 - T.J. Crowder
@Camilo:例如,有这个。我确信我听到过Prototype和jQuery库的开发人员对其他人(不仅仅是在IE中)发表评论。在短期内,我认为我可能会坚持使用json2.js或(如果我从不受信任或半受信任的来源解析数据)你在Crockford的github页面上指出的非eval json_parse.js和json_parse_state.js替代方案。 - T.J. Crowder
此外,自2.8.0以来,雅虎的JSON工具具有以下好用的属性:useNativeParseuseNativeStringify,可以禁用。但我仍然希望Firefox和Webkit不会干扰我的JSON。 - Camilo Martin
@Camilo:然而:https://bugzilla.mozilla.org/show_bug.cgi?id=509184 请注意,这是字符串化程序中的一个错误,但仍然存在。 - T.J. Crowder
1
@T.J. Crowder 我可以想象在脚本中寻找错误时,由于 JSON 处理问题而感到沮丧的情况。我不会期望错误出现在那里。在这些时候,能够简单地使用库的安全实现是至关重要的。 - Camilo Martin

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