調べてみるとCsrfProtectionMiddleware
を全体的に無効化していたり、
ルーティング設定に混ぜ込んでいたりするものが多かったのですが
今回はそれ以外の方法で良さそうなものがあったので紹介します。
まずは結論から
src/Application.php
でCsrfProtectionMiddleware
を
whitelistCallbackメソッド
でCSRF保護しないControllerを指定して読み込ませる。
バージョン
- CakaPHP 3.9.10
- (CakaPHP 3.8系 でも使えると思います)
ホワイトリスト登録
CakePHP4系だとCookBookに
ホワイトリストコールバック機能を使用して、 CSRF トークンチェックを実行する URL をより詳細に制御できます。
とあって実装の仕方を見ても楽そうだったので、CakePHP3系でもできないかなーとコアファイルを眺めていると
/**
* Set callback for allowing to skip token check for particular request.
*
* The callback will receive request instance as argument and must return
* `true` if you want to skip token check for the current request.
*
* @param callable $callback A callable.
* @return $this
*/
public function whitelistCallback(callable $callback)
{
$this->whitelistCallback = $callback;
return $this;
}
メソッドの名前はちょっと違うけどそれっぽいのがあるじゃないですか。
早速使ってみる
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Cake\Http\ServerRequest;
...
public function middleware($middlewareQueue)
{
$csrf = new CsrfProtectionMiddleware([
'httpOnly' => true
]);
$csrf->whitelistCallback(function (ServerRequest $request) {
// CSRFチェックしたくないcontrollerを指定
$skipedControllers = ['SampleApi'];
if(in_array($request->getParam('controller'),$skipedControllers)) {
return true;
}
// debugkitも除外
if($request->getParam('plugin') == 'DebugKit') {
return true;
}
return $request;
});
$middlewareQueue
...
// `new RoutingMiddleware($this, '_cake_routes_')`
->add(new RoutingMiddleware($this))
->add($csrf); // <-ミドルウェアのキューに追加
return $middlewareQueue;
}
これで試すと指定したControllerのみCSRF保護無効にできてました
IF文の中身を調整してAction単位にする等、自分好みのカスタマイズもしやすいです。
config/routes.php
でも似たようなことはできるんですが、
個人的にはそこにルーティング以外の役割を持たせたくないので
src/Application.php
のミドルウェア設定部分でやってしまうのがおススメです。
まとめ
CakePHP3でもホワイトリスト登録でCSRF保護を部分的に無効化できる。