この記事には広告を含む場合があります。
記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。
目次
POST 時に Security コンポーネントによるエラーが発生する
CakePHP では、Ajax などフォーム以外からの POST を行ったときに Security コンポーネントが403エラーを返します。通常はセキュリティの観点から見て嬉しい対応なのですが、ajax や外部サイトとの連携を行うときに邪魔になるときがあります。
そこで今回は、403エラーを出力する CsrfProtectionMiddleware の対処法を確認します。
CsrfProtectionMiddleware による403エラーの対処法
CakePHP3 では、ajax 等の POST を許容する方法がバージョンごとに違います。
・CakePHP3.4 以下
・CakePHP3.5 ~ CakePHP3.6
・CakePHP3.7 以降
で対応方法が異なるので順番に確認しましょう。
CakePHP3.4 以下の解決法
CakePHP3.4 以下のときは許容したい Controller 内の「beforeFilter」で「CSRF」を OFF にして、POSTを許容します。
各自のプログラム
1 2 3 4 5 6 7 8 9 |
public function beforeFilter(Event $event) { if($this->request->action == 'hogehoge'){ $this->getEventManager()->off($this->Csrf); } } public function hogehoge() { //外部サイトからのPOSTが受付可能 } |
CakePHP3.5 ~ CakePHP3.6 の解決法
CakePHP3.5 から「CsrfProtectionMiddleware」により、 Controller 内で CSRF の OFF が行えないので、まず「Application.php」にある「CsrfProtectionMiddleware」をコメントアウトします。その上で、各 Controller をラッパーするクラスに CSRF コンポーネントを設定して、個別の Controller 内で「beforeFilter」で CSRF を OFF にします。
cakephp/src/Application.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public function middleware($middlewareQueue) { $middlewareQueue ->add(ErrorHandlerMiddleware::class) ->add(new AssetMiddleware([ 'cacheTime' => Configure::read('Asset.cacheTime') ])) ->add(new RoutingMiddleware($this, '_cake_routes_')); /* // Add csrf middleware. ->add(new CsrfProtectionMiddleware([ //'secure' => true, 'httpOnly' => true ])); */ return $middlewareQueue; } |
各自のプログラムで生成する Controller のラッパークラス
1 2 3 4 5 6 7 |
class AppliController extends Controller { public function initialize() { parent::initialize(); $this->loadComponent('Csrf'); } |
各自のプログラム
1 2 3 4 5 6 7 8 9 |
public function beforeFilter(Event $event) { if($this->request->action == 'hogehoge'){ $this->getEventManager()->off($this->Csrf); } } public function hogehoge() { //外部サイトからのPOSTが受付可能 } |
CakePHP3.7 以降の解決法
CakePHP3.7 以降は「Application.php」にあった「CsrfProtectionMiddleware」が「routers.php」にあるため、「routers.php」で対処する必要があります。
「CsrfProtectionMiddleware」記述場所の変更点の詳細については、下記を参照してください。
https://github.com/cakephp/app/commit/040cddab8e13960e5ebce5dcc3dadbedde39e683#diff-c9248b3167fc44af085b81db2e292837
routers.php
1 2 3 4 5 6 7 |
Router::scope('/', function (RouteBuilder $routes) { /* // Register scoped middleware for use in routes.php $routes->registerMiddleware('csrf', new CsrfProtectionMiddleware([ 'httpOnly' => true ])); */ |
各自のプログラムで生成する Controller のラッパークラス
1 2 3 4 5 6 7 |
class AppliController extends Controller { public function initialize() { parent::initialize(); $this->loadComponent('Csrf'); } |
各自のプログラム
1 2 3 4 5 6 7 8 9 |
public function beforeFilter(Event $event) { if($this->request->action == 'hogehoge'){ $this->getEventManager()->off($this->Csrf); } } public function hogehoge() { //外部サイトからのPOSTが受付可能 } |
さいごに
CakePHP の入力規制は試行錯誤しているのかマイナーバージョンごとに記入方法が異なります。実装する場合は十分にお気を付けください。