Hatena::Groupsubtech

冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。

 | 

Oct 11, 2012 (Thu)

サーバサイドからデータの受け渡しに data-* を使う 12:32 はてなブックマーク - サーバサイドからのデータの受け渡しに data-* を使う - 冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。

(大した話ではないですが、だいぶ前にどっかで話して以来ブログに書いてなかったようです)

サーバサイドのプログラムからクライアントサイドの JavaScript に何かしらのデータを受け渡しする場合というは、XSS を作りやすい部分であります

<script>
var User = {
  id : [% user.id | js %],
  name : "[% user.name | js %]"
};
</script>

このようにテンプレートエンジンを使って script の中で何らかの変数を展開するような場合HTML としてのエスケープと、JavaScript としてのエスケープ正しい順番で行う必要があるか、あるいは専用のフィルタ関数を作るなどが必要になります。すなわち、いずれにせよ正しい処理方法を覚えて、毎回間違えずに使う必要があります。これらは、正しい知識を持つエンジニアが正しい実装をして正しい使いかたをできれば問題ないと言えますが、そんな面倒なこと覚えていられねーよという話ですし、人間は忘れるものですから本質的危険です。


なので、最近僕が使っている方法が data-* で値を受け渡す方法です。

これは例えば html 要素や、body 要素などに data-* を適当に生やしてデータを渡すというだけです。

<!DOCTYPE html>
<html
  data-user-id="[% user.id | html %]"
  data-user-name="[% user.name | html %]"
  >
...

<script>
alert(document.documentElement.getAttribute('data-user-id'));
</script>

こうすることで、変数エスケープは常に HTML 用のをかけるだけですみます。これはすなわち、デフォルトHTMLエスケープをするテンプレートエンジン (普通はそう) を使う場合には、余計なエスケープ心配をする必要が一切なくなります意図的にミスしようとしない限りミスれないので安全です。

data-* を付ける要素

data-* を付ける要素は、なんでもいいですが、できるだけドキュメント上に早く登場するほうがスクリプトから使いやすいです。

html 要素であれば、document.documentElement で簡単にアクセスできるし、スクリプト実行時には必ず存在するので変数の取得に関しては問題ありませんが、クローラーによっては先頭の n bytes をとってきて title 要素を抜き出すみたいなことをやっていたりするので、大量のデータを入れるには向かないようです (html 要素でええやん! と使いまくってたら mala さんに指摘されました)

body 要素でも、document.body で簡単にアクセスできるし便利なんですが、body 要素に到達するまでは変数の読みとりができない点に注意する必要があります。どうしても header 要素内の script 要素で読みこんでいる JS の中で同期的に変数を読みとりたい! という場合は使えないことになります

当然、他の要素でも data-* をつけることはできるので、ついでにつけておいて取得するようなこともよくやっています

構造データは?

頑張って展開して埋めこむか、専用の API を作ってあとから読みこむのが一番安全だと思います。どうしてもやりたいときだけ従来の方法を非常に注意して使うとかしかなさそうです。

 | 

スポンサード リンク

書いてる人

cho45 (佐藤広央) (www.lowreal.net)

Perl, JavaScript, Ruby, HTML, CSS, Web etc


スポンサード リンク