対象読者
- JavaScriptテンプレートエンジンに興味のある方
- JavaScript、jQueryの基本を理解している方
必要な環境と準備
JsRenderとjQueryを以下のサイトからダウンロードしてください。詳しくは、前回を参照してください。
JsRenderでHTMLを出力する際の注意点
前回は、JsRenderが出力したテキストをメッセージボックス内に表示しました。実際にJsRenderを使う際は、HTMLを出力し、それをHTMLページに表示することが多いでしょう。
JsRenderでHTMLを出力するには、テンプレート内にHTMLタグを直接記述します。出力したHTMLを表示するには、jQueryのhtmlメソッドを用いてHTML要素と置き換えます。
その際、JsRenderは{{:プロパティ名}}をプロパティの値にそのまま置き換えます。そのため、データモデルの値中にscriptタグが書かれていると、scriptタグがHTML中に書き込まれ実行されてしまいます。
<!-- 1. テンプレートの定義 -->
<script id="itemTemplate" type="text/x-jsrender">
<b>{{:name}}</b>の値段は<b>{{:price}}円</b>です。<br/>
重さは<b>{{:weight}}グラム</b>です。<br/>
</script>
<!-- 2. HTMLを表示するdiv要素 -->
<div id="placeholder"></div>
<script type="text/javascript"><!--
// 3. データモデルの定義
var item = {
name: "みかん<script>alert();</script>",
price: 100,
weight: 60
};
// 4. テンプレートを使ったテキストの生成
var result = $("#itemTemplate").render(item);
// 5. div要素の中身を入れ替える
$("#placeholder").html(result);
//--></script>
- HTMLを出力するテンプレートを定義します。テンプレート内にHTMLタグを直接記述します。
- HTMLを表示するdiv要素を定義します。
- データモデルを定義します。nameプロパティの中にscriptタグが書かれていることに注意してください。
- JsRenderのrenderメソッドを呼び出し、HTMLを出力します。
- jQueryのhtmlメソッドを呼び出し、3で定義したdiv要素の中身を置き換えます。
<b>みかん<script>alert();</script></b>の値段は<b>100円</b>です。<br/> 重さは<b>60グラム</b>です。<br/>
このように、意図しないスクリプトを実行させることは、クロスサイトスクリプティングと呼ばれ、ページを書き換えられたり情報漏洩の原因になるなど、多くの問題を引き起こします。
この問題を解決するためには、コンバーターを使ってプロパティの値を安全な形に変換してから出力します。
HTMLコンバーター
{{:プロパティ名}}の代わりに{{html:プロパティ名}}と記述すると、JsRenderは値をHTMLエンコードしてから出力します。HTMLエンコードすると、<や>等のようにHTMLを記述するうえで特別な意味を持つ文字は、そうでない文字に変換されます。
{{html:プロパティ名}}の代わりに{{>プロパティ名}}という表記も可能です。{{html:プロパティ名}}と{{>プロパティ名}}は同義です。
<script id="itemTemplate" type="text/x-jsrender">
<b>{{>name}}</b>の値段は<b>{{>price}}円</b>です。<br/>
重さは<b>{{>weight}}グラム</b>です。<br/>
</script>
<b>みかん<script>alert();</script></b>の値段は<b>100円</b>です。<br/> 重さは<b>60グラム</b>です。<br/>
この値を変換する機能をコンバーターと呼び、{{html:プロパティ名}}や{{>プロパティ名}}と記述することで、HTMLコンバーターを指定できます。
| 変換前 | 変換後 |
|---|---|
| & | & |
| < | < |
| > | > |
| \x00 | � |
| ' | ' |
| " | " |
| ` | ` |
JsRenderには標準で3種類のコンバーターが備わっており、HTMLコンバーターの他に、属性コンバーターとURLコンバーターがあります。
