はじめに
こんばんは。
今回もまたcakephp3の話です。
外部とのやり取りを行う開発をしており、 外部からのコールバック時に csrfチェックをスルーさせるようなロジックが必要になりました。
その際の対応を備忘録として残しておきます。
本題
現在3.6系のcakephp3を使用中で、その際は、 Application.phpの以下の場所で CsrfProtectionMiddleware
を使用しています。
cakephp4以降になると、CsrfProtectionMiddlewareに whitelistCallback()というメソッドが実装され、ホワイトリスト形式でcsrf保護を通すようなロジックを書ける場所を提供してくれています。
/** * 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; }
ちなみに、4.1以降になると、 whitelistCallback()
は非推奨になり、代わりに、 skipCheckCallback()
を使うように勧められます。
/** * 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 skipCheckCallback(callable $callback) { $this->skipCheckCallback = $callback; return $this; }
ただし、cakephp3にはこれはありません。 なので、それっぽいのを作る感じになります。
今回作ったのは、 CsrfProtectionMiddleware
をextendsした、 AppCsrfProtectionMiddleware
です。
<?php namespace App\Middleware; use Cake\Http\Middleware\CsrfProtectionMiddleware; use Cake\Http\Response; use Cake\Http\ServerRequest; class AppCsrfProtectionMiddleware extends CsrfProtectionMiddleware { private const WHITE_LIST_REQUESTS = [ 'Example' => '*', 'Example2' => ['index', 'callback'], ]; public function __invoke(ServerRequest $request, Response $response, $next) { $requestParams = $request->getAttributes()['params']; foreach (self::WHITE_LIST_REQUESTS as $controller => $actions) { if ($requestParams['controller'] !== $controller) { continue; } if ($actions === '*') { return $next($request, $response); } foreach ($actions as $action) { if ($requestParams['action'] === $action) { return $next($request, $response); } } } return parent::__invoke($request, $response, $next); } }
WHITE_LIST_REQUESTS
に Controller
=> Action
という感じで定義していくことで、該当のActionに対しては csrfの保護を外すことが出来ます。
終わりに
ということで、こんなのを実装しましたが、cakphp4系になればこんな独自実装は必要なくなるので、早めにあげられたらいいなと思う日でした。
現場からは以上です。