対象読者
- 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コンバーターがあります。