2012-02-16 18 views
79

estoy pensando en la incorporación de JSON arbitraria en el DOM como esto:¿La mejor práctica para incorporar JSON arbitrario en el DOM?

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

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

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

This works, pero ¿es la mejor manera? ¿Viola esto alguna mejor práctica o estándar?

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

+1

¿por qué no tener como 'var' en javascript – Krizz

+0

@Krizz, tiene que ser parte de un documento estático que más tarde se procesa mediante un complejo? cadena de javascript encapsulado. Almacenarlo en el DOM es lo que quiero hacer. –

+0

@Krizz Me plantearon un problema similar. Quería poner datos en un sitio diferente para cada usuario sin hacer una solicitud AJAX. Así que incrusté algo de PHP en un contenedor, hice algo similar a lo que tienes arriba para obtener los datos en javascript. –

Respuesta

61

Creo que su método original es el mejor. La especificación HTML5 incluso direcciones de este uso:

línea

"Cuando se usa para incluir bloques de datos (a diferencia de los scripts), los datos deben estar incrustadas, el formato de los datos se deben especificar con el atributo de tipo, el atributo src no debe especificarse, y el contenido del elemento script debe cumplir los requisitos definidos para el formato utilizado. "

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

Usted ha hecho exactamente eso. que es no amar? Sin codificación de caracteres según sea necesario con datos de atributos. Puede formatearlo si lo desea. Es expresivo y el uso previsto es claro. No se siente como un hack (por ejemplo, si usa CSS para ocultar su elemento "carrier"). Es perfectamente válido.

+2

Gracias. La cita de la especificación me ha convencido. –

+15

Es perfectamente válido solo si primero verifica y desinfecta el objeto JSON: no puede simplemente incrustar los datos de origen del usuario. Ver mi comentario sobre la pregunta. – silviot

+1

extra wondering: ¿cuál es el buen lugar para ponerlo? cabeza o cuerpo, arriba o abajo? – challet

18

Como dirección general, trataría de usar HTML5 data attributes en su lugar. No hay nada que te impida poner JSON válido. por ejemplo:

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

Si estás usando jQuery, y luego recuperando es tan fácil como:

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

Tiene sentido. Sin embargo, tenga en cuenta que con comillas simples para el nombre de la clave, 'JSON.parse' no funcionará (al menos, el JSON.parse nativo de Google Chrome no lo hará). La especificación JSON requiere comillas dobles. Pero eso es bastante fácil de arreglar usando entidades como '... <unicornios>: ...'. –

+4

Una pregunta: ¿Hay algún límite en la longitud de los atributos en HTML 5? –

+0

Sí, eso funcionaría. También puede cambiarlo para que su HTML use comillas simples y los datos JSON utilicen el doble. –

5

me gustaría sugerir que poner JSON en una secuencia de comandos 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 de que el documento se puede almacenar esto en alguna parte, posiblemente con un argumento identificador adicional: someCallback("stuff", { ... });

+0

Gracias por la sugerencia, pero eso no funciona para mis propósitos. –

+0

@BenLee debería funcionar muy bien, con la única desventaja de tener que definir la función de devolución de llamada. La otra solución sugerida se rompe en caracteres HTML especiales (por ejemplo, &) y comillas, si los tiene en su JSON. – copy

+0

Esto se siente mejor porque no necesita una consulta dom para encontrar los datos – Jaseem

2

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

+9

No pone CSS y Javascript en línea en una página web porque generalmente se comparte entre otras páginas. Si los datos en cuestión son generados por el servidor explícitamente para este contexto, incrustarlos es mucho más eficiente que iniciar otra solicitud de algo que no se puede almacenar en caché. –

+0

Es porque estoy realizando actualizaciones de un sistema heredado que se diseñó mal, y en lugar de rediseñar todo el sistema, solo tengo que arreglar una parte. El almacenamiento de JSON en el DOM es la mejor manera de solucionar esta parte. Además, estoy de acuerdo con lo que dijo @jamietre. –

+0

@jamietre Tenga en cuenta que el OP indicó que esta cadena JSON solo es necesaria * más tarde *. La pregunta es si se necesita siempre, o solo en algunos casos. Si solo es necesario en algunos casos, tiene sentido tenerlo en un archivo externo y solo cargarlo condicionalmente. –

10

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

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

Aquí es 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 alrededor de escape/codificación.

+5

Esto es cierto, pero en realidad no es una falla de seguridad del método. Si alguna vez coloca algo que se originó en la entrada del usuario en sus páginas, debe ser diligente para evitarlo. Este método sigue sonando siempre que tome las medidas de precaución normales con respecto a la entrada del usuario. –

+0

JSON no es parte de HTML, el analizador de HTML simplemente continúa. Es lo mismo que cuando el JSON sería parte de un párrafo de texto o div-element. HTML: escapa del contenido de tu programa. Además, también puedes escapar de las barras. Si bien JSON no lo requiere, sí tolera las barras innecesarias. Que se puede utilizar con el fin de hacer que sea seguro para incrustar. El json_encode de PHP hace esto por defecto. – Krinkle

0

Consulte Rule #3.1 en la hoja de información sobre prevención XSS de OWASP.

Digamos que quiere incluir este JSON en HTML:

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

Crear una oculta <div> en HTML. A continuación, escapar de su JSON mediante la codificación de entidades inseguras (por ejemplo, &, <,>,",', 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 se puede acceder a él mediante la lectura de la textContent de el elemento utilizando JavaScript y analizarlo:

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