Eval - это зло… Так что же мне использовать вместо этого?

StackOverflow https://stackoverflow.com/questions/646597

  •  22-07-2019
  •  | 
  •  

Вопрос

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

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

Какой из них мне следует использовать?Существует ли стандартный, проверенный и безопасный способ сделать это?

Это было полезно?

Решение

json.org имеет замечательную библиотеку JavaScript

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

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

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

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

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

Другие советы

  

Существует ли стандартный, проверенный и надежный способ сделать это?

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

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

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

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

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

:)

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

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

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

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

Проблема: Проблема, которую создает 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

Сценарий:

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

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

Вы хотели бы получить все элементы с этим атрибутом, превратить onvisible-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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top