Лучшая практика для внедрения произвольного 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">
{"html":"<script>alert(\"XSS!\");</script>"}
</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 ' quotes"
}
'></data>