JSON.parse против eval ()

94

My Spider Sense предупреждает меня, что использование eval()для анализа входящего JSON - плохая идея. Мне просто интересно, является ли JSON.parse()- которое, как я полагаю, является частью JavaScript, а не функцией, специфичной для браузера, - более безопасно.

Кевин Мейджор
источник
По производительности JSON.parseон быстрее, чем eval, по крайней мере, в V8 (движок Chromium JS). Источник .
Пол

Ответы:

110

Вы более уязвимы для атак, если используете eval: JSON - это подмножество Javascript, а json.parse просто анализирует JSON eval, оставляя дверь открытой для всех выражений JS.

jldupont
источник
«Вы более уязвимы для атак» , я полностью не согласен!
Hydroper
4
Извини, Матеус, я должен согласиться. Проблема в том, что вы используете eval () для интерпретации «пользовательского ввода», который является ЛЮБЫМ источником, внешним по отношению к вашему JavaScript (включая возвращаемые значения из сервлетов или других вызванных вами веб-сервисов). Вы не можете гарантировать, что пользователи не вводили вредоносный код JavaScript ни непосредственно в ваше клиентское приложение, ни косвенно из-за непроверенных данных, хранящихся в базе данных сервера и затем переданных вашей программе через вызов в стиле AJAX. Возможно, вам все равно придется проверять отдельные поля, чтобы избежать атак «запутанного заместителя», но использование JSON.parse - хороший первый шаг.
JackLThornton
1
@Hydro Краткое подтверждение концепции: попробуйте eval('alert(1)');.
Валерио Бозз
37

Все JSON.parseреализации, скорее всего, используютeval()

JSON.parseоснован на решении Дугласа Крокфорда , которое используется eval()прямо в строке 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 + ')');

Преимущество JSON.parseзаключается в том, что он проверяет правильность синтаксиса JSON аргумента.

трудяга
источник
56
да, за исключением того, что строка прямо перед этим подтверждает, что это безопасная и допустимая строка.
nickf
6
Я тестировал JSON.parse()Firefox 28 и Chromium 33 в своей системе Linux Mint. Это было в 2 раза быстрее, чем eval()в Firefox, и в 4 раза быстрее в Chromium. Я не уверен, какой исходный код вы публикуете, но в моих браузерах они разные.
jbo5112
@plodder "преимущество", вероятно, не из дешевых для проверки.
ммм
2
Современные браузеры предоставляют встроенную JSON.parse()реализацию, которая безопаснее и быстрее, чем eval()синтаксические анализаторы.
Mohammad Alhashash
15

Не все браузеры имеют встроенную поддержку JSON, поэтому будут случаи, когда вам нужно использовать eval() строку JSON. Используйте парсер JSON с http://json.org, так как он сделает все для вас намного проще.

Eval() это зло, но против некоторых браузеров это неизбежное зло, но если вы можете избежать этого, сделайте это !!!!!

AutomatedTester
источник
12

Есть разница между тем, что принимают JSON.parse () и eval (). Попробуйте eval на этом:

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

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

См. Этот пример .

Джефф Лоури
источник
1
eval не работает, потому что он анализирует строки как операторы кода и, таким образом, рассматривает "{...}" как выражение кода вместо выражения объявления значения. если вы удалите двусмысленность (например, «[{....}]»), не останется никаких сомнений в природе выражения, и eval создаст массив, содержащий проанализированный объект
Charles HETIER
1
Да. Традиционно x будет заключаться в круглые скобки: eval ("(" + x + ")"). То, что я сказал, остается в силе: при использовании JSON.parse () нет двусмысленности.
Джефф Лоури
9

Если вы анализируете JSON с помощью eval, вы позволяете анализируемой строке содержать абсолютно все, поэтому вместо простого набора данных вы можете выполнять вызовы функций или что-то еще.

Кроме того, JSON parseпринимает дополнительный параметр, reviver, который позволяет вам указать, как работать с определенными значениями, такими как datetime (дополнительная информация и пример во встроенной документации здесь )

Дэвид Хедлунд
источник
4

JSON - это всего лишь подмножество JavaScript. Но evalоценивает весь язык JavaScript, а не только подмножество JSON.

Гамбо
источник
Хорошо, я это знаю. Вы подразумеваете, что JSON.parse () ТОЛЬКО оценивает JSON и не работает со всеми другими входящими данными? Или это просто оболочка для: var myObject = eval ('(' + responseText + ')'); ??
Кевин Мэйджор,
6
@Kevin Major: Да, изначально реализованный JSON.parse(непосредственно реализованный в движке JavaScript) анализирует только JSON. Но другие реализации, не являющиеся исходными, выполняют некоторую проверку evalработоспособности, а затем используют их по соображениям производительности.
Gumbo