CakePHP & PHP 2006/12/15 17:45
CakePHPでCSRF対策
CakePHPでCSRF対策を行う方法です。
フレームワークに含まれているSecurityコンポーネントを使います。
Security#requestAuth()にアクションを記述しておくと、アクション実行前に正規リクエストかどうかをチェックします。チェックの方法はCSRF対策で一般的なワンタイムトークン方式です。
まずController#beforeFilter()にてチェックを行うアクションを指定します。
[app/controller/test_controller.php]
-
<?php
-
class TestController extends AppController {
-
var $name = 'Test';
-
-
function beforeFilter() {
-
$this->Security->requireAuth('add', 'edit');
-
}
-
-
function add() {
-
//
-
}
-
-
function edit() {
-
//
-
}
-
}
-
?>
あとはビューファイルにトークンを埋め込みます。ポイントはformタグをHTMLで書かずにHtmlHelper#formTag()で記述するという事です。そうしておけばフレームワークがトークンをhiddenで埋め込んでくれます。(もとからformTag()で記述されている場合はそのままで良いです。)
[app/views/test/add.thtml]
実行時のHTMLソースは以下のような感じになります。(トークンの値は表示毎に変化します。)
トークンが一致しないリクエストが発生した場合は[HTTP/1.0 404 Not Found]が出力されます。(この動作は変更できます。)
上記は一つのコントローラでチェックを行っていますが、全てのフォームで同様のチェックを行うならSecurity#requestAuth()をAppController#beforeFileter()に書いておけばokです。
[app/app_controller.php]
-
<?php
-
class AppController extends Controller {
-
-
function beforeFilter() {
-
$this->Security->requireAuth('add', 'edit');
-
}
-
}
-
?>
こうしておけば全てのControllerでadd/editアクションを実行する前にチェックがかかります。
ワンタイムトークン方式ではコントローラ/モデル側とビュー側の双方に記述が必要なのですが、フレームワーク側で考慮されているので手軽に使用できます。
ただ残念ながらbakeで生成したビューファイルはformタグがHTMLで書かれており、いちいち上記のように書き換える必要があります。HtmlHelperはデフォルトで読み込まれるのでformTag()で書いておいてくれれば楽なのですが。
# 気が向いたらTicket投げておきます。
■Related Posts
- CakePHP解説本を書きました
- CakePHP1.1.12.4205&1.2.0.4206_devリリース
- CakePHP Screencastまとめ
- CakeMatsuriにまつわる7つの疑問
- CakePHPのコーディング規約




on 21 12月 2006 at 11:04 1.shun said …
今、ためしてみたんですが、$html->formTag($html->url('/test/add/'.$html->tagValue('test/id')) というのは、単に $html->formTag() とするか、 $html->formTag('/test/add/'.$html->tagValue('test/id')) としたほうがよさそうですね。formTag() の中でも url() を呼んでるみたいです。どうでしょうか?
on 21 12月 2006 at 12:28 2.shin@1x1 said …
ですね。冗長な表現でした。
表示ページ自身にsubmitするなら前者、違うページにsubmitするなら後者ですね。
エントリも修正しておきました。
ありがとうございました。:-)
on 25 1月 2008 at 20:32 3.【CakePHP】CSRF対策でSecurityComponentを使う場合の注意点 | ねねとまつの小部屋 said …
[...] Shin x blogさんCakePHPでCSRF対策 [...]