CakePHP の Security コンポーネント の動作を調べたのでまとめておきます。
この Security コンポーネントをうまく使用すればクロスサイトリクエストフォージェリ(CSRF) を防ぐことができるでしょう。

トークンの使用

フォームにワンタイムトークンを実装する方法です。

コントローラの beforeFilter メソッドでトークンをチェックするアクションを指定
function beforeFilter() {
    $this->Security->requireAuth('login');
}
ビューのフォーム内にトークンを設定

<?php echo $html->formTag(); ?>
トークンが hidden 属性で生成される

トークンが一致しない場合

requireAuth で指定したアクションに POST でアクセスがあるとセションに保存したトークンとフォームから送られてきたトークンが一致するかチェックします。またそのほかにトークンの有効期間もチェックします。有効期間は CAKE_SECURITY の設定により違います。

CAKE_SECURITY 有効期間
high 10分
medium 100分
low 300分

トークンが一致しないと SecurityComponent の blackHole メソッドが実行されます。このメソッドでは
header('HTTP/1.0 404 Not Found');
を出力して exit します。(画面は空白)

任意の処理を実行したい場合は blackHoleCallback でコールバック関数を指定します。
設定できるのは同じコントローラ内のアクションのみになります。

function beforeFilter() {
    $this->Security->blackHoleCallback = "securityError";
    $this->Security->requireAuth('login');
}

function securityError() {
	die("security error!");
}
トークンチェックをするアクションを複数指定するときはカンマでつなげる

$this->requireAuth('login', 'delete');

特定のコントローラからのポストのみ許可する

$this->Security->allowedControllers = array("users");
これを指定するとたとえトークンが一致しても許可のないコントローラからのポストの場合は blackHole メソッドを実行します。

特定のアクションからのポストのみ許可する

$this->Security->allowedActions = array("action");
これを指定するとトークンが一致しても許可のないアクションからのポストの場合は blackHole メソッドを実行します。

ポストのみ受け付けるようにする

$this->requirePost('login');
これはトークンとは違い、POST のみ許可して GET でのアクセスを不可にします。
/users/login/ のような URL でのアクセスも GET なので不可になります。
POST の処理だけを実行したいようなアクションに使用します。

関連する投稿