Javascript 在DOM中嵌入任意JSON的最佳实践?
我考虑在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的替代方案,我已经决定这是解决我遇到的特定问题的最佳解决方案。我只是在寻找最好的方法。作为
<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">
{"html":"<script>alert(\"XSS!\");</script>"}
</div>
var text = document.querySelector('#init_data').textContent;
var json = JSON.parse(text);
console.log(json); // {html: "<script>alert("XSS!");</script>"}