今回のお題
今回はdjangoテンプレートのエスケープについてまとめます。
例によって自分用のメモです。
目次
- エスケープとは
- safeフィルター
- autoescapeフィルター
- escapeフィルター
- templatetag、verbatimブロック
エスケープとは
エスケープとは、{{}}や{%%}で囲まれた部分の特殊文字、すなわち<や&などを他の文字に置き換えることを言います。
なぜこのようなことをしているのかというと、{{}}や{%%}の中の特殊文字が有効になっているとページの内容を書き換えることが可能になるからですね。
例えば以下のようなテンプレートがあったとして、フォームに入力された文字列が表示されるとします。
<!-- フォームに入力された内容を表示 -->
{{ msg }}
このときにもし以下のようなメッセージが作られると、フォームには文字列ではなく画像が表示されることになります。
msg = "<img src='xxxxxx'>"
<!-- 特殊文字をエスケープしなかった場合 -->
<img src='xxxxxx'>
このような状況を回避するために、{{}}や{%%}には特殊文字をエスケープする仕組みが備わっているというわけです。
safeフィルター
では、逆に何らかの事情でエスケープを無効化したい場合にはどうすれば良いのでしょうか。
その場合にはsafeフィルターをかけることで特殊文字をそのまま解釈させることができます。
msg = "<strong>python</strong>"
<div>{{ msg }}を勉強する</div>
<!-- 以下のように解釈される -->
<div><strong>python</strong></div>
autpescapeフィルター
複数箇所でエスケープをまとめて無効化したい場合には、autoescapeタグが便利です。
{% autoescape off %}
{% for msg in msgs %}
{{ msg }}
{% endfor %}
{% endautoescape %}
また、autoescapeブロックの中で特定箇所だけエスケープを有効にしたいという場合には、escapeフィルターを用います。
{% autoescape off %}
{{ msg1 }}
{{ msg2 }}
{{ msg3|escape }}<!-- ここだけエスケープあり -->
{% endautoescape }}
templatetag、verbatimブロック
これらのタグは、{{}}や{%%}などのテンプレート予約文字をそのまま出力するのに使います。
まずtemplatetagに関しては、{% templatetag xxx %}というコードをテンプレートに埋め込むことでそれに対応した予約文字が表示されます。
templatetagの一例
| 入力 | 出力 |
|---|---|
| openvariable | {{ |
| closevariable | }} |
| opencomment | {# |
| closecomment | #} |
| openbrace | { |
| openbrace | } |
例えば
{% templatetag opencomment %}
<span>テスト</span>
{% templatetag closevariable %}
上記のコードであれば、
{# テスト }}
となりますね。
また、複数の予約文字をそのまま表示したい場合にはverbatimブロックが便利です。
このブロックで囲まれた部分は予約文字が全てそのまま出力されるので、例えば
{% verbatim block %}
{{ msg }}
{% endverbatim block %}
とすれば
{{ msg }}
とそのまま出力されます。
blockはverbatimブロックごとの識別子なので、ブロックが一つであれば省略可能です。
終わりに
エスケープについては以上です。
もちろんサイトの脆弱性を考慮するとエスケープを使わないに越したことはないですが、仕組みは知っておいて損はないですね。