Je pense à incorporer du JSON arbitraire dans le DOM comme ceci:
<script type="application/json" id="stuff">
{
"unicorns": "awesome",
"abc": [1, 2, 3]
}
</script>
Cette procédure est similaire à celle utilisée pour stocker un modèle HTML arbitraire dans le DOM pour une utilisation ultérieure avec un moteur de modèle JavaScript. Dans ce cas, nous pourrions récupérer plus tard le JSON et l’analyser avec:
var stuff = JSON.parse(document.getElementById('stuff').innerHTML);
Cela fonctionne , mais est-ce la meilleure façon? Est-ce que cela enfreint les meilleures pratiques ou normes?
Remarque: je ne cherche pas d'autres solutions que le stockage de JSON dans le DOM. J'ai déjà décidé que c'était la meilleure solution au problème que je rencontrais. Je cherche juste le meilleur moyen de le faire.
Je pense que votre méthode originale est la meilleure. La spécification HTML5 répond même à cette utilisation:
"Lorsqu'elles sont utilisées pour inclure des blocs de données (par opposition aux scripts), les données doivent être incorporées en ligne, le format des données doit être défini à l'aide de l'attribut type, l'attribut src ne doit pas être spécifié et le contenu de l'élément de script doit être défini. conformes aux exigences définies pour le format utilisé. "
Lire ici: http://dev.w3.org/html5/spec/Overview.html#the-script-element
Vous avez fait exactement cela. Ce qui est de ne pas aimer? Pas de codage de caractères nécessaire avec les données d'attribut. Vous pouvez le formater si vous voulez. C'est expressif et l'utilisation prévue est claire. Cela ne ressemble pas à un bidouillage (par exemple, si vous utilisez CSS pour masquer votre élément "transporteur"). C'est parfaitement valide.
En règle générale, j'essaierais d'utiliser attributs de données HTML5 . Rien ne vous empêche de mettre en JSON valide. par exemple.:
<div id="mydiv" data-unicorns='{"unicorns":"awesome", "abc":[1,2,3]}' class="hidden"></div>
Si vous utilisez jQuery, le récupérer est aussi simple que:
var stuff = JSON.parse($('#mydiv').attr('data-unicorns'));
Cette méthode d’incorporation de JSON dans une balise de script présente un problème de sécurité potentiel. En supposant que les données json proviennent de l'entrée de l'utilisateur, il est possible de créer un membre de données qui se détachera de la balise script et autorisera une injection directe dans le dom. Vois ici:
Voici l'injection
<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>
Il n'y a tout simplement pas moyen de s'échapper/encoder.
Voir règle 3.1 dans le aide-mémoire de prévention XW de OWASP.
Supposons que vous souhaitiez inclure ce JSON en HTML:
{
"html": "<script>alert(\"XSS!\");</script>"
}
Créez un <div>
Caché en HTML. Ensuite, sortez de votre code JSON en encodant des entités non sécurisées (par exemple, &, <,>, ", 'et//) et insérez-le dans l'élément.
<div id="init_data" style="display:none">
{"html":"<script>alert(\"XSS!\");</script>"}
</div>
Vous pouvez maintenant y accéder en lisant le textContent
de l'élément à l'aide de JavaScript et en l'analysant:
var text = document.querySelector('#init_data').textContent;
var json = JSON.parse(text);
console.log(json); // {html: "<script>alert("XSS!");</script>"}
Je suggèrerais de mettre JSON dans un script en ligne avec une fonction de rappel (genre de JSONP ):
<script>
someCallback({
"unicorns": "awesome",
"abc": [1, 2, 3]
});
</script>
Si le script d'exécution est chargé après le document, vous pouvez le stocker quelque part, éventuellement avec un argument d'identificateur supplémentaire: someCallback("stuff", { ... });
Ma recommandation serait de conserver les données JSON en externe .json
fichiers, puis récupérez ces fichiers via Ajax. Vous ne mettez pas de code CSS et JavaScript sur la page Web (en ligne), alors pourquoi le feriez-vous avec JSON?
HTML5 comprend un <data>
élément pour conserver les données lisibles par machine. Comme alternative peut-être plus sûre à <script type="application/json">
vous pouvez inclure vos données JSON dans l'attribut value
de cet élément.
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>
Dans ce cas, vous devez remplacer tous les guillemets simples par '
ou avec "
si vous choisissez de mettre la valeur entre guillemets. Sinon, vos risques XSS attaques comme d'autres réponses l'ont suggéré.