2010-07-13 31 views
5

我注意到,jQuery的parseJSON基本上没有一个简单的正则表达式“检查”:如果它传递的是“检查”,如果它是一个现代的浏览器中使用本地JSON解析器应该使用jQuery的parseJSON/getJSON方法吗?

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); 
    } 
}, 

。否则,我假设像IE6这样的浏览器会自动调用一个新函数并返回该对象。

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

问题#2:多少“更安全”是(new Function(" return " + data))()而不是eval("(" + text + ")")

回答

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那里也有直接引用约翰Resig。

0

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

+3

如果本机JSON不可用,json2.js将使用相同的正则表达式,然后使用'eval'。 – 2010-07-13 15:50:05

+0

已注意。感谢澄清。 – spoulson 2010-07-13 17:23:56