web-dev-qa-db-ja.com

DOMに任意のJSONを埋め込むためのベストプラクティスですか?

私は次のようにDOMに任意のJSONを埋め込むことを考えています:

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

これは、後でJavaScriptテンプレートエンジンで使用するためにDOMに任意のHTMLテンプレートを保存する方法に似ています。この場合、あとでJSONを取得して解析できます。

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

これは動作します 、しかしそれが最良の方法ですか?これはベストプラクティスまたは標準に違反しますか?

注:私は、DOMにJSONを保存する代替手段を探していません。それが、私が抱えている特定の問題に対する最善の解決策であるとすでに決めています。最善の方法を探しているだけです。

99
Ben Lee

オリジナルの方法が最適だと思います。 HTML5仕様は、この使用にも対応しています。

「(スクリプトではなく)データブロックを含めるために使用する場合、データはインラインで埋め込む必要があり、データの形式はtype属性を使用して指定する必要があり、src属性は指定してはならず、script要素のコンテンツは使用される形式に定義された要件に準拠します。」

ここを読む: http://dev.w3.org/html5/spec/Overview.html#the-script-element

あなたはまさにそれをやった。愛さないのは何ですか?属性データに必要な文字エンコーディングはありません。必要に応じてフォーマットできます。それは表現力豊かで、意図された使用法は明確です。ハックのようには感じません(たとえば、CSSを使用して「キャリア」要素を非表示にしているように)。それは完全に有効です。

71
Jamie Treworgy

一般的な方向として、代わりに HTML5データ属性 を使用してみます。有効なJSONを入力するのを止めるものは何もありません。例えば。:

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

JQueryを使用している場合は、次のように簡単に取得できます。

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

Jsonをスクリプトタグに埋め込むこの方法には、潜在的なセキュリティ上の問題があります。 jsonデータがユーザー入力に由来すると仮定すると、実際にはスクリプトタグから抜け出し、domに直接注入できるデータメンバーを作成することができます。こちらをご覧ください:

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

これが注入です

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

エスケープ/エンコードを回避する方法はありません。

12
MadCoder

OWASPのXSS防止チートシートの ルール#3.1 を参照してください。

このJSONをHTMLに含めるとします。

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

非表示の<div> HTML。次に、安全でないエンティティ(&、<、>、 "、 '、および/など)をエンコードしてJSONをエスケープし、要素内に配置します。

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

JavaScriptを使用して要素のtextContentを読み取り、解析することでアクセスできます。

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

関数コールバック( [〜#〜] jsonp [〜#〜] )を使用してJSONをインラインスクリプトに配置することをお勧めします。

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

実行スクリプトがドキュメントの後にロードされる場合、おそらく追加の識別子引数を使用して、これをどこかに保存できます:someCallback("stuff", { ... });

5
copy

私の推奨事項は、JSONデータを外部.jsonファイル、およびAjaxを介してそれらのファイルを取得します。 CSSおよびJavaScriptコードをWebページに(インラインで)配置しないので、なぜJSONを使用するのですか?

2
Šime Vidas

HTML5には、機械可読データを保持するための <data>要素 が含まれています。おそらくより安全な<script type="application/json">の代替として、その要素のvalue属性内にJSONデータを含めることができます。

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>

この場合、値を二重引用符で囲むことを選択した場合は、すべての単一引用符を&#39;または&quot;に置き換える必要があります。そうでなければ、あなたのリスク [〜#〜] xss [〜#〜] 他の答えのような攻撃が示唆しています。

0
Rúnar Berg