Лучшая практика для внедрения произвольного JSON в DOM?

Я думаю о встраивании произвольного JSON в DOM, как это:

<script type="application/json" id="stuff">
    {
        "unicorns": "awesome",
        "abc": [1, 2, 3]
    }
</script>

Это похоже на способ хранения произвольного HTML-шаблона в DOM для последующего использования с движком JavaScript. В этом случае мы могли бы позже получить JSON и проанализировать его с помощью:

var stuff = JSON.parse(document.getElementById('stuff').innerHTML);

Это работает, но это лучший способ? Это нарушает какую-либо лучшую практику или стандарт?

Примечание. Я не ищу альтернативы хранению JSON в DOM, я уже решил, что это лучшее решение для конкретной проблемы, с которой я сталкиваюсь. Я просто ищу лучший способ сделать это.

Ответ 1

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

"При использовании для включения блоков данных (в отличие от сценариев) данные должны быть встроены в ряд, формат данных должен быть указан с использованием атрибут типа, атрибут src не указывается, а содержимое элемента script должно соответствовать требованиям определенный для используемого формата.

Читайте здесь: http://dev.w3.org/html5/spec/Overview.html#the-script-element

Вы сделали именно это. Что не любить? Никакая кодировка символов по мере необходимости с данными атрибута. Вы можете отформатировать его, если хотите. Это выразительное и предполагаемое использование ясно. Это не похоже на взлом (например, использование CSS для скрытия вашего элемента "carrier" ). Это совершенно верно.

Ответ 2

В качестве общего направления я попытался бы использовать атрибуты данных HTML5. Нет ничего, что помешало бы вам вставить действительный JSON. например:

<div id="mydiv" data-unicorns='{"unicorns":"awesome", "abc":[1,2,3]}' class="hidden"></div>

Если вы используете jQuery, то получение его так же просто, как:

var stuff = JSON.parse($('#mydiv').attr('data-unicorns'));

Ответ 3

Этот метод вложения json в тег script имеет потенциальную проблему безопасности. Предполагая, что данные json возникли из пользовательского ввода, можно создать элемент данных, который фактически выйдет из тега script и разрешит прямое вложение в dom. См. Здесь:

http://jsfiddle.net/YmhZv/1/

Вот инъекция

<script type="application/json" id="stuff">
{
    "unicorns": "awesome",
    "abc": [1, 2, 3],
    "badentry": "blah </script><div id='baddiv'>I should not exist.</div><script type="application/json" id='stuff'> ",
}
</script>

Существует только способ избежать экранирования/кодирования.

Ответ 4

Я бы предложил включить JSON в встроенный script с функцией обратного вызова функции (вид JSONP):

<script>
someCallback({
    "unicorns": "awesome",
    "abc": [1, 2, 3]
});
</script>

Если исполняемый script загружается после документа, вы можете его сохранить где-нибудь, возможно с дополнительным аргументом идентификатора: someCallback("stuff", { ... });

Ответ 5

См. Правило № 3.1 в шпаргалке по профилактике OWASP XSS.

Скажем, вы хотите включить этот JSON в HTML:

{
    "html": "<script>alert(\"XSS!\");</script>"
}

Создайте скрытый <div> в HTML. Затем, выйдите из JSON, кодируя небезопасные объекты (например, &, <,>, ", 'и,/) и поместите его в элемент.

<div id="init_data" style="display:none">
        {&#34;html&#34;:&#34;&lt;script&gt;alert(\&#34;XSS!\&#34;);&lt;/script&gt;&#34;}
</div>

Теперь вы можете получить к нему доступ, прочитав textContent элемента с помощью JavaScript и проанализировав его:

var text = document.querySelector('#init_data').textContent;
var json = JSON.parse(text);
console.log(json); // {html: "<script>alert("XSS!");</script>"}

Ответ 6

Моя рекомендация состояла бы в том, чтобы хранить данные JSON во внешних файлах .json, а затем извлекать эти файлы через Ajax. Вы не помещаете код CSS и JavaScript на веб-страницу (встроенный), так почему бы вам сделать это с помощью JSON?

Ответ 7

HTML5 включает элемент <data> для хранения машиночитаемых данных. В качестве (возможно, более безопасной) альтернативы <script type="application/json"> вы можете включить свои данные JSON в атрибут value этого элемента.

const jsonData = document.querySelector('.json-data');
const data = JSON.parse(jsonData.value);

console.log(data)
<data class="json-data" value='
  {
    "unicorns": "awesome",
    "abc": [1, 2, 3],
    "careful": "to escape &#39; quotes"
  }
'></data>