Эваль злой... Так что я должен использовать вместо этого?

Запрос ajax возвращает мне стандартный массив JSON, заполненный моими пользовательскими вводами. Ввод был дезинфицирован, и с помощью функции eval() я могу легко создать свой javascript-объект и обновить мою страницу...

Итак, вот проблема. Независимо от того, насколько я стараюсь дезинформировать исходные данные, я бы предпочел не использовать функцию eval(). Я проверил google о способах использования "JSON в AJAX без eval" и пробежал по множеству разных методов...

Какой я должен использовать? Есть ли стандартный, проверенный и безопасный способ сделать это?

Ответ 1

json.org имеет приятную javascript library

простое использование:

JSON.parse('[{"some":"json"}]');
JSON.stringify([{some:'json'}]);

Изменить. Как указано в комментариях, это использует eval, если вы просматриваете его источник (хотя сначала он нуждается в санитации)

чтобы полностью избежать этого, посмотрите json_parse или json-sans-eval

json2.js небезопасен, json_parse.js медленный, json-sans-eval.js не проверяется

Ответ 2

Существует ли стандартный безопасный способ?

В предлагаемой версии ECMAScript 3.1 JavaScript предлагается предлагаемый стандартный способ: JSON.parse.

Он будет поддерживаться в IE8, Firefox 3.1/3.5 и, скорее всего, в других популярных браузерах в будущем. Тем временем вы можете вернуться или использовать исключительно eval(). Зло это может быть или не быть; конечно, это будет медленнее, чем JSON.parse. Но это обычный способ разобрать JSON сегодня.

Если злоумышленник может внедрить злостный JavaScript в контент, который вы выплевываете через JSON, у вас больше проблем, чем беспокоиться, чем eval-is-evil.

Ответ 3

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

Не беспокойтесь об eval. Но не забудьте обернуть его в блок try... catch, чтобы ваши пользователи не получали JS-ошибки, если ваш JSON становится искаженным.

:)

Ответ 4

Чтобы безопасно преобразовать JSON в объект JS, вы должны использовать JSON-анализатор, такой как функция JSON.parse(), предоставленная этой библиотекой.

Ответ 5

Сравните с шаблоном проектирования команд: http://en.wikipedia.org/wiki/Command_pattern. Учитывая это, вы можете точно определить операции, которые может выполнить клиент, и ваше приложение будет столь же безопасным, как и основная интерпретация.

Ответ 6

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

Ответ 7

Если вы уверены, что нет риска инъекций, а вы не eval()ing в цикле, используйте eval(). Он будет выгодно сравнивать с другими параметрами, которые, безусловно, будут медленнее, могут сломаться и потребуют от клиента загрузки дополнительного кода.

Ответ 8

"украден" из jQuery

// Try to use the native JSON parser first
return window.JSON && window.JSON.parse ?
    window.JSON.parse( data ) :
    (new Function("return " + data))();

Ответ 9

Вопрос: Задача eval заключается в том, что она выполняется в глобальной области

eval.call(document, "console.log(this)")
eval.call(navigator, "console.log(this)")
eval.call(window, "console.log(this)")
(function(){eval.call(document, "console.log(this)")})()
>Window

Сценарий:

Предположим, что вы используете отдельные атрибуты в коде разметки различных элементов документа, таких как атрибут onvisible

<img src="" onvisible="src='http://www.example.com/myimg.png';">

Вы хотели бы получить все элементы с этим атрибутом, превратить строку invisible-content-string в закрытие и поместить ее в очередь EventHandler. Здесь вступает в действие конструктор функции JS.

Function === 0..constructor.constructor
>true

Function('return [this, arguments]').call(window, 1,2,3)
>Window, Arguments[3]]
Function('return [this, arguments]').call(document, 1,2,3)
>Document, Arguments[3]]
Function('return [this, arguments]').call(navigator, 1,2,3)
>Navigator, Arguments[3]]    

Объединяя все это:

var eventQueue = [];
var els = document.querySelectorAll('[onvisible]');

for (var el in els) {
    var jscode = els[el].getAttribute('onvisible');
    eventQueue.push( {el:els[el], cb:Function(jscode)} )
}

//eventQueue[0].cb.call(scope, args);