JSON.parse vs. eval ()

94

Mein Spider Sense warnt mich, dass eval()es eine schlechte Idee ist, eingehende JSONs zu analysieren. Ich frage mich nur, ob JSON.parse()- was meiner Meinung nach Teil von JavaScript und keine browserspezifische Funktion ist - sicherer ist.

Kevin Major
quelle
In Bezug auf die Leistung JSON.parseist es schneller als evalzumindest in V8 (Chromiums JS-Engine). Quelle .
Paul

Antworten:

110

Sie sind anfälliger für Angriffe, wenn Sie evalFolgendes verwenden : JSON ist eine Teilmenge von Javascript, und json.parse analysiert nur JSON, während evaldie Tür für alle JS-Ausdrücke offen bleibt .

jldupont
quelle
"Sie sind anfälliger für Angriffe" , stimme ich überhaupt nicht zu!
Hydroper
4
Entschuldigung, Matheus, ich muss zustimmen. Das Problem besteht darin, dass Sie eval () verwenden, um "Benutzereingaben" zu interpretieren. Dies ist JEDE Quelle außerhalb Ihres JavaScript (einschließlich der von Servlets oder anderen von Ihnen aufgerufenen Webdiensten zurückgegebenen Werte). Sie können nicht garantieren, dass Benutzer weder direkt in Ihre Client-App noch indirekt bösartiges JavaScript eingegeben haben, weil nicht validierte Daten in der Datenbank des Servers gespeichert und dann über einen AJAX-Aufruf an Ihr Programm weitergeleitet wurden. Möglicherweise müssen Sie noch einzelne Felder validieren, um "verwirrte Stellvertreter" -Angriffe zu vermeiden. Die Verwendung von JSON.parse ist jedoch ein guter erster Schritt.
JackLThornton
1
@Hydro Kurzer Proof of Concept: versuchen eval('alert(1)');.
Valerio Bozz
37

Alle JSON.parseImplementierungen werden höchstwahrscheinlich verwendeteval()

JSON.parsebasiert auf der Lösung von Douglas Crockford , die eval()genau dort in Zeile 497 verwendet wird .

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

j = eval('(' + text + ')');

Der Vorteil von JSON.parseist, dass überprüft wird, ob das Argument die richtige JSON-Syntax hat.

Arbeitstier
quelle
56
Ja, außer dass die Zeile direkt davor bestätigt, dass es sich um eine sichere und gültige Zeichenfolge handelt.
Nickf
6
Ich habe JSON.parse()in Firefox 28 und Chromium 33 auf meinem Linux Mint-System getestet . Es war 2x so schnell wie eval()in Firefox und 4x so schnell in Chrom. Ich bin nicht sicher, welchen Quellcode Sie veröffentlichen, aber sie sind in meinen Browsern nicht dasselbe.
jbo5112
@plodder "Vorteil" ist wahrscheinlich nicht billig, um diese Überprüfung durchzuführen.
mmm
2
Moderne Browser bieten eine native JSON.parse()Implementierung, die sicherer und schneller ist als eval()Parser auf Basis.
Mohammad Alhashash
15

Nicht alle Browser bieten native JSON-Unterstützung, daher müssen Sie manchmal eval() die JSON-Zeichenfolge verwenden. Verwenden Sie den JSON-Parser von http://json.org, da dies alles für Sie viel einfacher macht.

Eval() ist ein Übel, aber gegen einige Browser ist es ein notwendiges Übel, aber wo Sie es vermeiden können, tun Sie dies !!!!!

AutomatedTester
quelle
12

Es gibt einen Unterschied zwischen dem, was JSON.parse () und eval () akzeptieren. Versuchen Sie es mit einer Bewertung:

var x = "{" einkaufenKartenname ":" einkaufskart: 2000 "}"

eval(x)         //won't work
JSON.parse(x)   //does work

Siehe dieses Beispiel .

Jeff Lowery
quelle
1
eval funktioniert nicht, weil es Zeichenfolgen als Code-Anweisungen analysiert und daher "{...}" als Code-Ausdruck anstelle eines Wertdeklarationsausdrucks betrachtet. Wenn Sie die Mehrdeutigkeit entfernen (z. B. "[{....}]"), besteht kein Zweifel an der Art des Ausdrucks, und eval erstellt ein Array mit dem analysierten
Objekt
1
Ja. Traditionell wird x in Klammern gesetzt: eval ("(" + x + ")"). Was ich gesagt habe, bleibt bestehen: Bei der Verwendung von JSON.parse () gibt es keine Mehrdeutigkeit.
Jeff Lowery
9

Wenn Sie den JSON mit analysieren eval, lassen Sie zu, dass die zu analysierende Zeichenfolge absolut alles enthält. Anstatt nur ein Datensatz zu sein, können Sie Funktionsaufrufe ausführen oder was auch immer.

Außerdem parseakzeptiert JSON einen zusätzlichen Parameter, reviver, mit dem Sie angeben können, wie mit bestimmten Werten wie Datumsangaben umgegangen werden soll (weitere Informationen und Beispiele in der Inline-Dokumentation hier ).

David Hedlund
quelle
4

JSON ist nur eine Teilmenge von JavaScript. Aber evalwertet die volle Sprache JavaScript und nicht nur die Teilmenge , die JSON ist.

Gumbo
quelle
Richtig, das weiß ich. Wollen Sie damit sagen, dass JSON.parse () NUR JSON auswertet und bei allen anderen eingehenden Daten fehlschlägt? Oder ist es einfach ein Wrapper für: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major
6
@ Kevin Major: Ja, das nativ implementierte JSON.parse(direkt in die JavaScript-Engine implementierte) analysiert nur JSON. Andere nicht-native Implementierungen führen jedoch eine Überprüfung der Integrität durch und verwenden sie dann evalaus Leistungsgründen.
Gumbo