2010-11-17 62 views
14

json2.js嚴格要求所有對象鍵都用雙引號。但是,在Javascript語法中,{"foo":"bar"}相當於{foo:"bar"}使用未加引號的鍵安全解析JSON字符串

我有接受來自用戶的JSON輸入,並希望「緩和」的限制雙引號鍵一個文本。我已經看過json2.js如何在四個階段驗證一個JSON字符串,然後它纔會對它進行處理。我能夠添加第5個階段來允許不帶引號的鍵,並想知道這個邏輯是否存在任何安全隱患。

var data = '{name:"hello", age:"23"}'; 

// 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, ":") // EDITED: allow key:[array] by replacing with safe char ":" 
    /** everything up to this point is json2.js **/ 

    /** this is the 5th stage where it accepts unquoted keys **/   
    .replace(/\w+\s*\:/g, ":"))) { // EDITED: allow any alphanumeric key 

    console.log((new Function("return " + data))()); 
} 
else { 
    throw("Invalid JSON: " + data); 
} 
+4

您認爲JavaScript Object Literal等價於JSON,事實並非如此。 – Stephen 2010-11-17 23:28:13

+6

'{name:「Joe」}'是有效的Javascript,但它是_invalid_ JSON。你也不想破解'json2.js',因爲它只反映瀏覽器本機JSON支持的工作原理。例如,在Chrome中,沒有'json2.js'的'JSON.parse()'也會窒息。但更糟糕的是,如果瀏覽器具有本地JSON支持,那麼'json2.js'不會加載任何內容。因此,您將處於一種情況,即使用本機JSON支持的瀏覽器從不會看到這種黑客行爲,因爲它使用本機代碼來解析它。 – 2010-11-17 23:29:01

+0

@Stephen你是對的。也許我應該改爲「安全解析JavaScript對象文字和轉換爲JSON」的問題? – daepark 2010-11-17 23:33:50

回答

0

JSON不允許未加引號的鍵。 JSON是JavaScript表示法的一個子集,並且不包含未加引號的鍵。將未加引號的鍵傳遞給幾乎任何JSON解析器都可能會拋出錯誤或返回「意外」結果。

希望這有助於

+3

當然,關於JSON是真的,但JavaScript確實允許在對象字面量中使用未加引號的鍵。這只是有點問題,因爲你不能使用不帶引號的破折號或保留字。然而,我認爲提問者已經知道這一點。 – JAL 2010-11-18 00:27:45

3
data.replace(/(['"])?([a-zA-Z0-9]+)(['"])?:/g, '"$2":'); 

,它將取代在參數名稱的單引號,並添加任何缺失。

+5

這似乎工作。除非你沒有處理下劃線。這是一個更新正則表達式:''hash.replace(/(['「])?([a-zA-Z0-9 _] +)([''])?:/ g,'」$ 2「:'); – 2011-03-14 18:57:04

+0

touche,謝謝你是一個疏忽 – 2011-03-16 19:22:02

+4

這個答案是非常完美的。嘗試'{a:['b','c']}'或'{a:「注意:發生了什麼。」} – powerboy 2012-08-25 22:25:06

1

我認爲讓實際的測試用例清除這個實現中的任何問題會很有幫助。我已經通過一些測試添加了一個名爲JSOL的github項目。請隨意填寫以添加並找到問題。謝謝。

https://github.com/daepark/JSOL