应该使用jQuery的parseJSON / getJSON方法吗?

时间:2010-07-13 15:42:54

标签: javascript json parsing

我注意到jQuery parseJSON基本上做了一个简单的正则表达式“check”:

parseJSON: function( data ) {
    if ( typeof data !== "string" || !data ) {
        return null;
    }

    // Make sure leading/trailing whitespace is removed (IE can't handle it)
    data = jQuery.trim( data );

    // Make sure the incoming data is actual JSON
    // Logic borrowed from http://json.org/json2.js
    if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
        .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {

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

    } else {
        jQuery.error( "Invalid JSON: " + data );
    }
},

如果它通过了“检查”,并且它是现代浏览器,则使用本机JSON解析器。否则,我假设对于像IE6这样的浏览器,会自动调用一个新函数并返回该对象。

问题#1 :由于这只是一个简单的正则表达式测试,这是不是容易出现某种模糊的边缘案例漏洞?对于那些至少不支持原生JSON解析的浏览器,我们真的不应该使用完整的解析器吗?

问题#2 :与(new Function(" return " + data ))()相比,eval("(" + text + ")")“更安全”多少?

2 个答案:

答案 0 :(得分:3)

正如评论中所提到的,jQuery的JSON解析器“借用”了从json2.js开始测试以查看JSON字符串是否有效的逻辑。这使得它“像最常见的非本机实现一样安全”,无论如何都是相当严格的:

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

我不明白为什么jQuery在检查本机实现之前运行正则表达式/替换,无论如何都会检查正确的JSON语法。似乎只有在没有本机实现的情况下才能加快速度。

问题2在另一个问题中是answered very well by bobince

  

这并不是一个很大的区别,但感觉是eval比新功能“更糟糕”。不是在安全性方面 - 面对不受信任的输入,它们同样无用,但希望你的webapp不会返回不受信任的JSON字符串 - 但是在语言级别的怪异方面,因此对优化的抵制。

请查看Nick Craver's answer以获得John Resig的直接引用。

答案 1 :(得分:0)

JSON.parse方法是最安全的。当您从http://www.json.org/js.html包含json2.js并由parseJSON / getJSON自动使用时,会定义此选项。它解析而不是执行JSON标记。