JSON.parse ve eval ()


94

Örümcek Duyumum, eval()gelen JSON'u ayrıştırmak için kullanmanın kötü bir fikir olduğu konusunda beni uyarıyor . Sadece merak ediyorum JSON.parse()- JavaScript'in bir parçası olduğunu ve tarayıcıya özgü bir işlev olmadığını varsayıyorum - daha güvenli.


Performans açısından en azından V8'den (Chromium'un JS motoru) JSON.parsedaha hızlıdır eval. Kaynak .
Paul

Yanıtlar:


110

Şunları kullanıyorsanız saldırılara karşı daha savunmasızeval olursunuz: JSON, Javascript'in bir alt kümesidir ve json.parse, JSON'u ayrıştırırken evalkapıyı tüm JS ifadelerine açık bırakır.


"Saldırılara karşı daha savunmasızsınız" , tamamen katılmıyorum!
Hydroper

5
Üzgünüm Matheus, kabul etmeliyim. Sorun, JavaScript'inizden HERHANGİ bir kaynak olan "kullanıcı girdisini" yorumlamak için eval () kullanmanızdır (servletlerden veya çağırdığınız diğer web hizmetlerinden döndürülen değerler dahil). Kullanıcıların kötü amaçlı JavaScript'i doğrudan istemci uygulamanıza girmediklerini veya sunucunun veritabanında depolanan doğrulanmamış veriler nedeniyle dolaylı olarak ve ardından AJAX tarzı bir çağrı yoluyla programınıza aktarmadıklarını garanti edemezsiniz. Yine de "kafa karıştırıcı yardımcısı" saldırılarını önlemek için ayrı alanları doğrulamanız gerekebilir, ancak JSON.parse kullanmak iyi bir ilk adımdır.
JackLThornton

1
@Hydro Kısa kavram kanıtı: deneyin eval('alert(1)');.
Valerio Bozz

37

JSON.parseBüyük olasılıkla tüm uygulamalareval()

JSON.parsedayalı olan Douglas Crockford çözümüyle kullanır, eval()üzerinde yazıyor hattı 497 .

// 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 + ')');

Bunun avantajı JSON.parse, bağımsız değişkenin doğru JSON sözdizimi olduğunu doğrulamasıdır.


56
evet, ancak ondan hemen önceki satır, bunun güvenli ve geçerli bir dize olduğunu doğruluyor.
nickf

6
JSON.parse()Linux Mint sistemimde Firefox 28 ve Chromium 33'te test ettim. Bu kadar hızlı 2x oldu eval()hızlı Chromium'da olarak Firefox'ta ve 4x. Hangi kaynak kodunu gönderdiğinizden emin değilim, ancak tarayıcılarımda aynı şey değiller.
jbo5112

@plodder "avantaj" muhtemelen bunu doğrulamak için ucuz değildir.
mmm

2
Modern tarayıcılar , tabanlı ayrıştırıcılardan JSON.parse()daha güvenli ve daha hızlı olan yerel uygulama sağlar eval().
Mohammad Alhashash

15

Tüm tarayıcılarda yerel JSON desteği bulunmadığından eval() , JSON dizesini kullanmanız gereken zamanlar olacaktır . Http: //json.org'daki JSON ayrıştırıcısını kullanın, çünkü bu sizin için her şeyi çok daha kolay halleder.

Eval() bir kötülük ama bazı tarayıcılara karşı gerekli bir kötülük ama ondan kaçınabileceğiniz yerde bunu yapın !!!!!


12

JSON.parse () ve eval () öğelerinin kabul edeceği arasında bir fark vardır. Bunun üzerinde değerlendirmeyi deneyin:

var x = "{\" shoppingCartName \ ": \" shopping_cart: 2000 \ "}"

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

Bu örneğe bakın .


1
eval, dizeleri kod ifadeleri olarak ayrıştırdığından ve bu nedenle "{...}" öğesini bir değer bildirimi ifadesi yerine bir kod ifadesi olarak kabul ettiğinden çalışmaz. belirsizliği kaldırırsanız (örneğin "[{....}]"), ifadenin niteliği konusunda hiçbir şüphe yoktur ve eval, ayrıştırılmış
nesneyi

1
Evet. Geleneksel olarak, x parantez içine alınır: eval ("(" + x + ")"). Söylediğim şey hala geçerli: JSON.parse () kullanılırken belirsizlik yok.
Jeff Lowery

9

JSON'u ile ayrıştırırsanız, ayrıştırılan evaldizenin kesinlikle herhangi bir şey içermesine izin verirsiniz, bu nedenle yalnızca bir veri kümesi olmak yerine, kendinizi işlev çağrılarını veya her neyse yürütürken bulabilirsiniz.

Ayrıca JSON parse, veri zamanları gibi belirli değerlerle nasıl başa çıkılacağını belirlemenize izin veren ek bir parametre olan reviver'ı da kabul eder (daha fazla bilgi ve burada satır içi belgelerde örnek )


4

JSON, JavaScript'in yalnızca bir alt kümesidir. Ancak eval, yalnızca JSON olan alt kümeyi değil, tam JavaScript dilini değerlendirir.


Doğru, bunu biliyorum. JSON.parse () işlevinin YALNIZCA JSON'u değerlendirdiğini ve diğer tüm gelen verilerde başarısız olduğunu mu ima ediyorsunuz? Veya basitçe şunun için bir sarmalayıcı mı: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major

6
@Kevin Major: Evet, yerel olarak uygulanan JSON.parse(doğrudan JavaScript motoruna uygulanan) yalnızca JSON'u ayrıştırır. Ancak, yerel olmayan diğer uygulamalar, bazı mantıklı kontroller yapar ve ardından evalperformans nedenleriyle kullanır.
Gumbo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.