この記事には広告を含む場合があります。
記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。
目次
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を許容します。
各自のプログラム
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
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 のラッパークラス
class AppliController extends Controller
{
public function initialize()
{
parent::initialize();
$this->loadComponent('Csrf');
}
各自のプログラム
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
Router::scope('/', function (RouteBuilder $routes) {
/*
// Register scoped middleware for use in routes.php
$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware([
'httpOnly' => true
]));
*/
各自のプログラムで生成する Controller のラッパークラス
class AppliController extends Controller
{
public function initialize()
{
parent::initialize();
$this->loadComponent('Csrf');
}
各自のプログラム
public function beforeFilter(Event $event) {
if($this->request->action == 'hogehoge'){
$this->getEventManager()->off($this->Csrf);
}
}
public function hogehoge() {
//外部サイトからのPOSTが受付可能
}
さいごに
CakePHP の入力規制は試行錯誤しているのかマイナーバージョンごとに記入方法が異なります。実装する場合は十分にお気を付けください。


