简体   繁体   English

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

[英]Best practice for embedding arbitrary JSON in the DOM?

I'm thinking about embedding arbitrary JSON in the DOM like this: 我正在考虑在DOM中嵌入任意JSON,如下所示:

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

This is similar to the way one might store an arbitrary HTML template in the DOM for later use with a JavaScript template engine. 这类似于可以在DOM中存储任意HTML模板以供以后与JavaScript模板引擎一起使用的方式。 In this case, we could later retrieve the JSON and parse it with: 在这种情况下,我们以后可以检索JSON并使用以下方法解析它:

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

This works , but is it the best way? 这有效 ,但这是最好的方法吗? Does this violate any best practice or standard? 这是否违反任何最佳做法或标准?

Note: I'm not looking for alternatives to storing JSON in the DOM, I've already decided that's the best solution for the particular problem I'm having. 注意:我不是在寻找在DOM中存储JSON的替代方法,我已经确定这是我遇到的特定问题的最佳解决方案。 I'm just looking for the best way to do it. 我只是在寻找最好的方法。

I think your original method is the best. 我认为你原来的方法是最好的。 The HTML5 spec even addresses this use: HTML5规范甚至解决了这个问题:

"When used to include data blocks (as opposed to scripts), the data must be embedded inline, the format of the data must be given using the type attribute, the src attribute must not be specified, and the contents of the script element must conform to the requirements defined for the format used." “当用于包含数据块(而不是脚本)时,数据必须内联嵌入,数据格式必须使用type属性给出,不得指定src属性,并且脚本元素的内容必须符合为所用格式定义的要求。“

Read here: http://dev.w3.org/html5/spec/Overview.html#the-script-element 在这里阅读: http//dev.w3.org/html5/spec/Overview.html#the-script-element

You've done exactly that. 你完全是这样做的。 What is not to love? 什么不爱? No character encoding as needed with attribute data. 属性数据不需要字符编码。 You can format it if you want. 您可以根据需要对其进行格式化。 It's expressive and the intended use is clear. 它具有表现力,预期用途很明确。 It doesn't feel like a hack (eg as using CSS to hide your "carrier" element does). 它不像是一个黑客(例如使用CSS来隐藏你的“载体”元素)。 It's perfectly valid. 这完全有效。

As a general direction, I would try using HTML5 data attributes instead. 作为一般方向,我会尝试使用HTML5数据属性 There's nothing to stop you putting in valid JSON. 没有什么可以阻止你输入有效的JSON。 eg: 例如:

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

If you're using jQuery, then retrieving it is as easy as: 如果你正在使用jQuery,那么检索它就像下面这样简单:

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

This method of embedding json in a script tag has a potential security issue. 这种在脚本标记中嵌入json的方法存在潜在的安全问题。 Assuming the json data originated from user input, it is possible to craft a data member that will in effect break out of the script tag and allow direct injection into the dom. 假设json数据源自用户输入,则可以创建一个数据成员,该成员实际上会脱离脚本标记并允许直接注入dom。 See here: 看这里:

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

Here is the 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>

There is just no way around escaping/encoding. 没有办法绕过/编码。

See Rule #3.1 in OWASP's XSS prevention cheat sheet. 请参阅OWASP的XSS预防备忘单中的规则#3.1

Say you want to include this JSON in HTML: 假设您要在HTML中包含此JSON:

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

Create a hidden <div> in HTML. 在HTML中创建隐藏的<div> Next, escape your JSON by encoding unsafe entities (eg, &, <, >, ", ', and, /) and put it inside the element. 接下来,通过编码不安全的实体(例如,&,<,>,“,”,和/)来转义JSON,并将其放在元素中。

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

Now you can access it by reading the textContent of the element using JavaScript and parsing it: 现在,您可以通过使用JavaScript读取textContent并解析它来访问它:

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

I'd suggest to put JSON into an inline script with a function callback (kind of JSONP ): 我建议将JSON放入带有函数回调的内联脚本(一种JSONP ):

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

If the executing script is loaded after the document you can store this somewhere, possibly with an additional identifier argument: someCallback("stuff", { ... }); 如果在文档之后加载执行脚本,您可以将其存储在某处,可能还有一个额外的标识符参数: someCallback("stuff", { ... });

My recommendation would be to keep JSON data in external .json files, and then retrieve those files via Ajax. 我的建议是将JSON数据保存在外部.json文件中,然后通过Ajax检索这些文件。 You don't put CSS and JavaScript code onto the web-page (inline), so why would you do it with JSON? 你没有把CSS和JavaScript代码放到网页上(内联),那你为什么要用JSON呢?

HTML5 includes a <data> element for keeping machine readable data. HTML5包含一个<data>元素,用于保存机器可读数据。 As a—perhaps safer—alternative to <script type="application/json"> you could include your JSON data inside the value attribute of that element. 作为<script type="application/json">的替代或许更安全的替代方法,您可以将JSON数据包含在该元素的value属性中。

 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 &#39; quotes" } '></data> 

In this case you need to replace all single quotes with &#39; 在这种情况下,您需要用&#39;替换所有单引号&#39; or with &quot; 或与&quot;&quot; if you opt to enclose the value with double quotes. 如果您选择用双引号括起该值。 Otherwise your risk XSS attacks like other answers have suggested. 否则你的风险XSS攻击就像其他答案一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM