Symfonyの最新安定版0.6.2で新しくEscaping Outputの機能が追加されました。 この仕組みが提案されてからリリースを待ち望んできましたが実に期待通りの機能でした。
Webアプリケーションでは、’< > &’などHTMLのメタ文字を’& lt; & gt; & amp;’のように変換する必要があります。もし、うっかり忘れるとクロスサイトスクリプティング(XSS)のようなセキュリティホールを発生させてしまう恐れがあるため確実にやらなくてはなりません。
SymfonyのEscaping Outputは、これらの変換を確実に行うための枠組みを提供します。
ここでは、以前からサンプルとして使っているBookmarkサンプルアプリケーションを例にSymfonyのEscaping Outputの仕組みを説明します。
エスケープ対応したチェンジセットも一緒に参照してください。
既存のエスケープを外す
いままでテンプレートに逐一入れていた、htmlspecialchars()関数を一旦すべて除去します。一つ一つ書くのは面倒でしたので外すのも面倒ですが、これで最後だと思えば苦になりません。
エスケープの設定
apps/frontend/config/view.yml に以下のようにescaping:設定を追加します。
default:
http_metas:
content-type: text/html; charset=utf-8
...
use_default_slots: on
escaping:
strategy: both
method: ESC_ENTITIESstrategy: method: についてはマニュアルを参照してください。この設定により、テンプレートのすべての変数がエスケープされるようになります。
ヘルパーのバグを修正する
この段階でUTF-8の文字が文字化けするのは、Symfony 0.6.2のバグで、下記のとおりEscapingHelperを修正しておく必要があります。
#463 output escaping function esc_entities is not utf-8 compliant
エスケープしないで出力する
逆に、エスケープされて困るテンプレート変数については今までとは違う方法で出力する必要があります。
もっともありがちな例は apps/frontend/templates/layout.php の
<?php echo $content ?>
の部分で、ここは以下のように $sf_data->getRaw(変数名)
<?php echo $sf_data->getRaw('sf_content') ?>
として書き換えます。 ここで利用している、$sf_dataコンテナは、テンプレート変数へのアクセスのため新規導入されました。
また、bookmark アプリケーションでは、BookmarkモデルのgetTrimedComment()メソッドが、HTMLを出力する仕様になっていますので、この出力のエスケープをしないようにします。
下記のようなコード
<div class="trimed_comment" id="bookmark_<?php echo $bookmark->getId() ?>_comment"><?php echo $bookmark->getTrimedComment() ?></div>
を、以下のように書き換えます。
<div class="trimed_comment" id="bookmark_<?php echo $bookmark->getId() ?>_comment"><?php echo $bookmark->getTrimedComment(ESC_RAW) ?></div>
$bookmark->getTrimedComment()の第一引数がフレームワークにより装飾されエスケープオプションを指定できるように拡張されています。ここに、エスケープしない(=ESC_RAW)を指定することでオブジェクトの出力をエスケープせずに出力することができます。
以上で、Escaping Outputの対応作業は終了です。 「問題のある部分をエスケープする」という従来の方針から「問題の無い部分をエスケープ対象から外す」とすることで、セキュリティホールを作りにくい仕組みになりました。
まだ本家のマニュアルに統合されていませんが、Escaping Outputのマニュアル(英語)も参考にしてください。

