2010-07-13 14 views
5

me di cuenta de que el jQuery parseJSON básicamente hace una expresión regular simple "marca":¿Se deberían usar los métodos parseJSON/getJSON de jQuery?

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

Si pasa que "verificar" y si se trata de un navegador moderno se utiliza un analizador JSON nativo. De lo contrario, supongo que para un navegador como IE6 se invoca automáticamente una nueva función y devuelve el objeto.

Pregunta n. ° 1: Dado que se trata de una simple prueba de expresión regular, ¿no es esto propenso a algún tipo de oscuro exploit de caso extremo? ¿No deberíamos estar usando un analizador completo, para los navegadores que no son compatibles con el análisis nativo de JSON al menos?

Pregunta # 2: ¿Cuánto "más seguro" es (new Function(" return " + data))() en comparación con eval("(" + text + ")")?

Respuesta

3

Como se menciona en los comentarios, el analizador JSON de jQuery "toma prestada" la lógica que prueba para ver si la cadena JSON es válida, directamente desde json2.js. Esto hace que sea "tan seguro", como la puesta en práctica no nativo más común, que es bastante estricta de todas formas:

// 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, ''))) {

Lo que no entiendo es por qué jQuery dirige la expresión regular/reemplaza antes de comprobar si una aplicación nativa lo que verificaría la correcta gramática JSON de todos modos. Parece que aceleraría las cosas solo para hacer esto si una implementación nativa no está disponible.

Pregunta 2 es answered very well by bobince en otra pregunta:

en realidad no es una gran diferencia, pero la sensación es que eval es ‘peor’ que la nueva función. No en términos de seguridad, ambos son igualmente inútiles frente a los datos que no son de confianza, pero con suerte su webapp no ​​está devolviendo cadenas JSON que no son de confianza, sino en términos de rareza a nivel de lenguaje y, por lo tanto, resistencia a la optimización.

Echa un vistazo Nick Craver's answer allí también para una cita directa de John Resig.

0

El método JSON.parse es el más seguro. Esto se define cuando se incluye json2.js desde http://www.json.org/js.html y se usa automáticamente por parseJSON/getJSON. Analiza en lugar de ejecutar el marcado JSON.

+3

json2.js usará la misma expresión regular, y luego 'eval', si el JSON nativo no está disponible. –

+0

observado. Gracias por aclararlo. – spoulson

Cuestiones relacionadas