SecurityComponentのトークンの仕様って1.1と1.2で変わってる?
1.2.0.7692および1.2.0.7692 RC3の情報ってことで。ちゃんとまとめて書けるといいんだけど、取り急ぎメモっとく。
再ロード対策として見始めた。現時点での認識では、この目的には使えなさそう(ちょっと自信なし)。クロスサイトリクエストフォージェリ(CSRF)対策としてとらえるべきか。
1.2で初めて試してみる。秋に見ていた1.1では試していなかった。事前に調べた情報では、リクエスト毎にトークンの値が変わるので使いにくいとの声も多数あり。
本家のドキュメントではあまり詳細な使い方が語られていないようなのだが、ざっくり次のように使うらしい。
- コントローラでSecurityコンポーネントの使用を宣言する。
- コントローラのbeforeFilterでSecurityComponent::requireAutメソッドを呼び出し、トークン認証するアクションを指定する。
- ビューでは、フォームの生成にFormHelper::createメソッドを使用することで、トークンがhidden項目として挿入される。
コントローラはこんな感じ。
class PostsController extends AppController { var $name = 'Posts'; var $components = array('Security'); // SecurityComponentを使う function beforeFilter() { parent::beforeFilter(); $this->Security->requireAuth('add', 'edit'); //トークン認証するアクションを指定 } function add() { ・・・ } function edit() { ・・・ } }
ビューはこんな感じ。
<?php echo $form->create('Post', array('action' => 'add')); // トークンのhiddenも出力 echo $form->input('title'); echo $form->input('body', array('rows' => '3')); echo $form->end('Save Post'); ?>
トークンのhiddenフィールドの例。
<input type="hidden" name="data[_Token][key]" value="89668b758b12435742behahahafdf3c092176876" id="Token1234567890" />
このトークンはセッションにも保存され、postされたとき(postのみ有効)に、リクエストパラメータとセッション上のトークンを比較してリクエストの有効性をチェックする。トークンは有効期限も持つ。
頭の中はStrutsのトークンのイメージ一色。こりゃええか?と試してみたところ、データ登録後に「最新の情報に更新(F5)」(IEだ)でバンバン登録できる。これが実戦なら私はもう死んでいる。
あれ、フォームで挿入されるトークンキーの値が毎回同じだ。
これって、リクエスト毎に更新されるんじゃなかったの?しばしネットを漂流するが有効な情報にはめぐりあえず。しかたなくCakePHPのソースを見る。ちっちゃくて、かわいいCakeなので、素人同然のボクでも何か分かることがあるかも。
cake/libs/controller/components/security.php
リクエスト(post)毎にトークンを更新するのだが、セッションに保存されているトークンのexpiration timeをチェックして、有効期限内ならトークンのキー値は前回のキー値を継続して使うようだ。トークンの有効期限は更新する(あたりまえだ)。
実際、有効期限が過ぎた後は新しいキー値がフォームに渡ってくる。
事前の認識と異なるので、1.1のソースも見てみた(1.1.20.7692)。1.1では、確かにリクエスト毎に新しいキー値を発行しているようだ(動かしてないっす。適当なこと言ってすんませんけど)。