Mejores prácticas para incrustar JSON arbitrario en el DOM?


Estoy pensando en incrustar JSON arbitrario en el DOM de esta manera:

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

Esto es similar a la forma en que uno podría almacenar una plantilla HTML arbitraria en el DOM para su uso posterior con un motor de plantillas JavaScript. En este caso, más tarde podríamos recuperar el JSON y analizarlo con:

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

Esto funciona, pero ¿es la mejor manera? ¿Viola esto alguna de las mejores prácticas o normas?

Nota: No estoy buscando alternativas para almacenar JSON en el DOM, ya he decidí que esa es la mejor solución para el problema particular que estoy teniendo. Estoy buscando la mejor manera de hacerlo.

Author: Paul Sweatte, 2012-02-17

6 answers

Creo que tu método original es el mejor. La especificación HTML5 incluso aborda este uso:

" Cuando se usa para incluir bloques de datos (a diferencia de scripts), los datos debe estar incrustado en línea, el formato de los datos debe proporcionarse utilizando el atributo type, el atributo src no se debe especificar, y el el contenido del elemento script debe ajustarse a los requisitos definido para el formato utilizado."

Leer aquí: http://dev.w3.org/html5/spec/Overview.html#the-script-element

Has hecho exactamente eso. ¿Qué es no amar? No se necesita codificación de caracteres con datos de atributos. Puedes formatearlo si quieres. Es expresivo y el uso previsto es claro. No se siente como un truco (por ejemplo, como el uso de CSS para ocultar su elemento "portador" lo hace). Es perfectamente válido.

 65
Author: Jamie Treworgy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-16 23:26:38

Como una dirección general, intentaría usar atributos de datos HTML5 en su lugar. No hay nada que te impida poner un JSON válido. por ejemplo:

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

Si está utilizando jQuery, recuperarlo es tan fácil como:

var stuff = JSON.parse($('#mydiv').attr('data-unicorns'));
 20
Author: Horatio Alderaan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-26 13:04:29

Este método de incrustar json en una etiqueta de script tiene un problema de seguridad potencial. Suponiendo que los datos json se originaron a partir de la entrada del usuario, es posible crear un miembro de datos que, en efecto, se desprenderá de la etiqueta de script y permitirá la inyección directa en el dom. Ver aquí:

Http://jsfiddle.net/YmhZv/1 /

Aquí está la inyección

<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>

Simplemente no hay manera de escapar/codificar.

 10
Author: MadCoder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-04 23:47:12

Sugeriría poner JSON en un script en línea con una función de devolución de llamada (tipo de JSONP):

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

Si el script de ejecución se carga después del documento, puede guardarlo en algún lugar, posiblemente con un argumento de identificador adicional: someCallback("stuff", { ... });

 6
Author: copy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-16 23:13:39

Mi recomendación sería mantener los datos JSON en archivos externos .json, y luego recuperar esos archivos a través de Ajax. No pones código CSS y JavaScript en la página web (en línea), así que ¿por qué lo harías con JSON?

 2
Author: Šime Vidas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-16 23:16:53

Ver Regla #3.1 en la hoja de trucos de prevención XSS de OWASP.

Digamos que desea incluir este JSON en HTML:

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

Crea un <div> oculto en HTML. A continuación, escape su JSON codificando entidades inseguras (p. ej., &, , ", ', y,/) y ponerlo dentro del elemento.

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

Ahora puedes acceder leyendo el textContent del elemento usando JavaScript y analizándolo:

var text = document.querySelector('#init_data').textContent;
var json = JSON.parse(text);
console.log(json); // {html: "<script>alert("XSS!");</script>"}
 1
Author: Matthew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-02 00:47:01