FuelPHPのセキュリティについての続き。
FuelPHPの出力エンコーディングと、ビューのセキュリティについて。
ちなみに「エンコーディング」とは、ある形式のデータを一定の規則に基づいて別の形式のデータに変換すること。「符号化」や「エンコード」とも呼ばれる。
逆に、エンコードされたデータをエンコード前に戻すことを「デコーディング(デコード)」と呼ぶ。
FuelPHPの出力エンコーディング
出力エンコーディングとは、ビューへ渡す変数を自動的に処理する機能のこと。
「はじめてのフレームワークとしてのFuelPHP」では出力フィルタと呼ばれている。
出力エンコーディングは、デフォルトで ONになっている。
設定は、app/config/cofig.phpで行なう。output_filterの項目を見つける。
/** * Security settings */ 'security' => array( output_filter' => array('Security::htmlentities'), )'
output_filter の設定はデフォルトでSecurity::htmlentitiesメソッドが指定されている。
ビューへ渡される変数は、このメソッドを通過することになる。
htmlentitiesメソッドは、HTML文字を実態参照に変換する。つまり、ビューに渡される文字列は htmlentities() でエスケープされることになる。
配列やオブジェクトにも適用できる。
ただし、ビューにオブジェクトを渡したい場合は、__toString()メソッドを持ってないとエラーになる。
これがビューにどのように実装されているかを見よう。
ビューのセキュリティ
ビューに渡される変数は全てサニタイズされて出力されます。デフォルトの状態では、セキュリティ関数である Security::htmlentities() が出力フィルタとして定義されています。フィルタはアプリケーションの config.php ファイルにて修正できます。 もしフィルタリングせずに変数を渡したい場合、set($name, $value, false) メソッドを使います。
ビューに渡される変数は全てサニタイズされて出力される、ってサニタイズ・・・?
htmlentitiesメソッドを通ってきたと解釈。
ビューへ値を渡すときの処理を見ていこう。
日本語ドキュメントより引用。
class Controller_Example extends Controller { public function action_index() { $view = \View::forge('example'); // フィルタして追加する、出力:<strong>not bold because filtered</strong> $view->title = '<strong>not bold because filtered</strong>'; //① // フィルタせず追加する、出力: <strong> bold because unfiltered</strong> $view->set('title', '<strong> bold because unfiltered</strong>', false); //② // または、set_safe() メソッドを使う。これは set() メソッドと同じだが、'false' が初期値 $view->set_safe('title', '<strong> bold because unfiltered</strong>'); //③ return $view; } }
①XSS対策としてフィルタを通す場合が最も簡単。
②フィルタせずに出力したい場合は、setメソッドを使う。その場合第3引数に falseが必要。
③②と同様にフィルタせずに出力したい場合に、set_safeメソッドを使う方法もある。こちらはデフォルトが falseなので注意。
フィルタせずに出力する方法には、②と③以外にも、View::forgeの第3引数に falseを使う方法がある。
最後に、オブジェクトについての注意を引用。
渡されるオブジェクトが View、ViewModel あるいは Closure のインスタンスでない限り、 オブジェクトは __toString() メソッドを持つことが期待され、出力フィルタリングが有効なとき文字列に強制変換されます。どうしても渡したい場合は、 set($name, $value, false) を使用する必要がありますが、 フィルタすることを決して忘れないで ください。
View以外のオブジェクトを渡すときには __toString()メソッドを持たないといけない。
これ、上で言ってたビューにオブジェクトを渡すときは __toString()を持ってないとエラーになるって話?
忘れそうだな。
コメント