Javascript 在DOM中嵌入任意JSON的最佳实践?

Javascript 在DOM中嵌入任意JSON的最佳实践?,javascript,json,dom,embedding,decoupling,Javascript,Json,Dom,Embedding,Decoupling,我考虑在DOM中嵌入任意JSON,如下所示: <script type="application/json" id="stuff"> { "unicorns": "awesome", "abc": [1, 2, 3] } </script> ,但这是最好的方法吗?这是否违反了任何最佳实践或标准 注意:我不是在寻找在DOM中存储JSON的替代方案,我已经决定这是解决我遇到的特定问题的最佳解决方案。我只是在寻找最好的方法。作为

我考虑在DOM中嵌入任意JSON,如下所示:

<script type="application/json" id="stuff">
    {
        "unicorns": "awesome",
        "abc": [1, 2, 3]
    }
</script>
,但这是最好的方法吗?这是否违反了任何最佳实践或标准


注意:我不是在寻找在DOM中存储JSON的替代方案,我已经决定这是解决我遇到的特定问题的最佳解决方案。我只是在寻找最好的方法。

作为一般指导,我会尝试使用。没有什么可以阻止您输入有效的JSON。e、 g:

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

我建议将JSON放入带有函数回调的内联脚本中(类似于):


一些回调({
“独角兽”:“棒极了”,
“abc”:[1,2,3]
});

如果执行脚本加载在文档之后,您可以将其存储在某个地方,可能还有一个附加的标识符参数:
someCallback(“stuff”,{…})

我的建议是将JSON数据保存在外部
.JSON
文件中,然后通过Ajax检索这些文件。你没有把CSS和JavaScript代码放在网页上(内联),那么为什么要用JSON呢?

我认为你原来的方法是最好的。HTML5规范甚至解决了这一问题:

当用于包含数据块(与脚本相反)时,数据 必须内嵌,数据的格式必须使用 不能指定type属性、src属性和 脚本元素的内容必须符合要求 为使用的格式定义。”

请看这里:


你确实做到了。什么是不爱?属性数据不需要字符编码。如果需要,可以格式化它。它的表现力和预期用途是明确的。这感觉不像是一种黑客行为(例如,使用CSS隐藏“carrier”元素)。这是完全正确的

这种在脚本标记中嵌入json的方法存在潜在的安全问题。假设json数据源于用户输入,则可以创建一个数据成员,该成员实际上将脱离脚本标记并允许直接注入dom。请看这里:

这是注射

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

{
“独角兽”:“棒极了”,
“abc”:[1,2,3],
“坏条目”:“我不应该存在。”,
}
无法绕过转义/编码。

请参见OWASP的XSS预防备忘单

假设您希望在HTML中包含此JSON:

{
    "html": "<script>alert(\"XSS!\");</script>"
}
HTML5包括一个用于保存机器可读数据的接口。作为一种可能比
更安全的选择,您可以将JSON数据包含在该元素的
属性中

const jsonData=document.querySelector('.json data');
const data=JSON.parse(jsonData.value);
console.log(数据)

为什么不将其作为javascript中的
var
使用?@Krizz,它需要是静态文档的一部分,然后由一个复杂的封装javascript链进行处理。将其存储在DOM中是我想要做的。@Krizz我遇到了一个类似的问题。我想在不做AJAX请求的情况下,为每个用户将数据放在不同的站点中。所以我在一个容器中嵌入了一些PHP,做了一些与上面类似的事情,以获取javascript中的数据。我认为您最初的方法实际上是最好的。它在HTML5中是100%有效的,它是表达性的,它不会创建“伪”元素,您只需使用CSS删除或隐藏这些元素;而且它不需要任何字符编码。缺点是什么?如果在JSON对象中有一个值为
alert()
的字符串,您会得到惊喜。除非首先对数据进行清理,否则这是不安全的。不过请注意,使用单引号作为键名,
JSON.parse
将不起作用(至少本机的Google Chrome JSON.parse不会起作用)。JSON规范需要双引号。但是,使用诸如
…unicorns:…
之类的实体来修复这一问题很容易。不过有一个问题:HTML5中的属性长度是否有限制?是的,这会起作用。您也可以将其切换为HTML使用单引号,JSON数据使用双引号。好的,找到了我问题的答案:--这对于我来说已经足够了。这对单个字符串不起作用,例如,
“我是有效的JSON”
并对标记使用双引号,或者在字符串中使用单引号,例如,
data unicorns='“My JSON's string”
作为单引号不会用JSON编码转义。您不会将CSS和Javascript内联到网页中,因为它通常在其他网页之间共享。如果所讨论的数据是由服务器显式地为此上下文生成的,那么嵌入该数据比启动另一个无法缓存的请求要高效得多。这是因为我正在更新一个设计糟糕的遗留系统,而不是重新设计整个系统,我只需要修复一个部分。在DOM中存储JSON是修复这一部分的最佳方法。另外,我同意@jamietre所说的。@jamietre注意到OP声明这个JSON字符串只在以后才需要。问题是它是否总是需要的,或者只是在某些情况下。如果只在某些情况下需要它,那么将它放在外部文件中并有条件地加载它是有意义的。我同意有许多“如果”可能会使天平倾斜。但一般来说,如果您知道页面何时呈现您将需要的内容(即使只是可能),通常最好立即发送它。比如,如果我有一些开始折叠的信息框,我通常希望将它们的内容内联,以便它们立即展开。新请求的开销与现有请求上的一点额外数据的开销相比要大得多,并且它创建了一个响应更快的用户体验。我确信有一个断点。@BenLee它应该工作得很好,唯一的缺点是必须定义回调函数。另一个建议的解决方案是在特殊的HTML字符(例如&)和引号(如果有的话)上中断
<script>
someCallback({
    "unicorns": "awesome",
    "abc": [1, 2, 3]
});
</script>
<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>
{
    "html": "<script>alert(\"XSS!\");</script>"
}
<div id="init_data" style="display:none">
        {&#34;html&#34;:&#34;&lt;script&gt;alert(\&#34;XSS!\&#34;);&lt;/script&gt;&#34;}
</div>
var text = document.querySelector('#init_data').textContent;
var json = JSON.parse(text);
console.log(json); // {html: "<script>alert("XSS!");</script>"}