2010-07-13 13 views
5

ho notato che la jQuery parseJSON fa fondamentalmente una semplice espressione regolare "check":Dovrebbero essere usati i metodi parseJSON/getJSON di 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); 
    } 
}, 

Se passa che "controllare" e se si tratta di un browser moderno si utilizza un parser JSON nativa. Altrimenti, presumo che per un browser come IE6 una nuova funzione venga richiamata automaticamente e restituisca l'oggetto.

Domanda n. 1: Poiché questo è solo un semplice test di regex, non è questo incline a una sorta di oscuro exploit caso limite? Non dovremmo davvero usare un parser completo, per i browser che non supportano l'analisi JSON nativa almeno?

Domanda n. 2: Quanto "più sicuro" è (new Function(" return " + data))() in contrapposizione a eval("(" + text + ")")?

risposta

3

Come accennato nei commenti, il parser JSON di jQuery "prende in prestito" la logica che verifica se la stringa JSON è valida, direttamente da json2.js. Questo lo rende "come sicuro", come l'implementazione non nativi più comuni, che è piuttosto rigorosa in ogni caso:

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

Quello che non capisco è il motivo per jQuery corre l'espressione regolare/sostituisce prima di controllare per un'implementazione nativa che controllerebbe comunque la grammatica JSON corretta. Sembra che acceleri le cose per farlo solo se non è disponibile un'implementazione nativa.

domanda 2 è answered very well by bobince in un'altra domanda:

Non è davvero una grande differenza, ma la sensazione è che eval è ‘peggio’ di nuova funzione. Non in termini di sicurezza - sono entrambi ugualmente inutili di fronte a input non attendibili, ma speriamo che la tua webapp non restituisca stringhe JSON non attendibili - ma in termini di stranezze a livello di linguaggio e quindi di resistenza all'ottimizzazione.

Check out Nick Craver's answer anche lì per una citazione diretta da John Resig.

0

Il metodo JSON.parse è il più sicuro. Questo viene definito quando includi json2.js da http://www.json.org/js.html e utilizzato automaticamente da parseJSON/getJSON. Analizza invece di eseguire il markup JSON.

+3

json2.js utilizzerà la stessa espressione regolare, quindi "eval', se il JSON nativo non è disponibile. –

+0

Notato. Grazie per il chiarimento. – spoulson

Problemi correlati