前提・実現したいこと
CakePHP4を使って、APIを実装したいと考えています。
API実装部分以外はログイン機能のあるシステムで、外部フォームから入力されたデータを
API機能を使ってデータベースに取り込み、システム内でデータを利用するという前提です。
発生している問題・エラーメッセージ
API以外の部分はログイン機能を実装しているため、元々はCakePHP全体にCSRF設定の有効化をしていましたが
Cookbookを参考にしつつ、API部分のみCSRFを無効化しようとしても、反映されません。
単純にAPIを提供しているURLを叩くとデータは表示されますが、別サーバーからcURL等でアクセスすると
以下のエラーが表示される、という状態です。
Missing or incorrect CSRF cookie type.
該当のソースコード
// routes.php // API $routes->scope('/api', ['prefix' => 'Api'], function (RouteBuilder $builder) { $builder->registerMiddleware('bodies', new BodyParserMiddleware()); $builder->applyMiddleware('bodies'); $builder->setExtensions(['json']); // Forms $builder->connect('/forms/search', ['controller' => 'Forms', 'action' => 'search'])->setMethods(['GET']); $builder->connect('/forms/create', ['controller' => 'Forms', 'action' => 'create'])->setMethods(['POST']); });
// Application.php public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue { $middlewareQueue // Catch any exceptions in the lower layers, // and make an error page/response ->add(new ErrorHandlerMiddleware(Configure::read('Error'))) // Handle plugin/theme assets like CakePHP normally does. ->add(new AssetMiddleware([ 'cacheTime' => Configure::read('Asset.cacheTime'), ])) // Add routing middleware. // If you have a large number of routes connected, turning on routes // caching in production could improve performance. For that when // creating the middleware instance specify the cache config name by // using it's second constructor argument: // `new RoutingMiddleware($this, '_cake_routes_')` ->add(new RoutingMiddleware($this)) // Parse various types of encoded request bodies so that they are // available as array through $request->getData() // https://book.cakephp.org/4/en/controllers/middleware.html#body-parser-middleware ->add(new BodyParserMiddleware()) // Cross Site Request Forgery (CSRF) Protection Middleware // https://book.cakephp.org/4/en/controllers/middleware.html#cross-site-request-forgery-csrf-middleware // ->add(new CsrfProtectionMiddleware([ // 'httponly' => true, // ])) ->add(new RoutingMiddleware($this)) // RoutingMiddleware の後に認証を追加 ->add(new AuthenticationMiddleware($this)); // CSRFに関する設定 $csrf = new CsrfProtectionMiddleware([ 'httponly' => true, ]); // コールバックが `true` を返す場合、トークンのチェックはスキップされます。 $csrf->skipCheckCallback(function ($request) { // Skip token check for API URLs. if ($request->getParam('prefix') === 'Api') { return true; } }); $middlewareQueue->add($csrf); return $middlewareQueue; }
// src/Controller/Api/FormsController.php <?php declare(strict_types=1); namespace App\Controller\Api; use App\Controller\AppController; use Cake\Cache\Cache; use Cake\Event\EventInterface; class FormsController extends AppController { public function initialize(): void { parent::initialize(); // TODO: Change the autogenerated stub $this->loadComponent('RequestHandler'); } /** * テスト用API(データ取得) */ public function search() { $forms = $this->Forms->find('all'); $this->set(compact('forms')); $this->viewBuilder()->setOption('serialize', ['forms']); } /** * データ登録API */ public function create() { $result = $this->request->getData(); $this->set(compact('result')); $this->viewBuilder()->setOption('serialize', ['result']); } public function beforeFilter(EventInterface $event) { parent::beforeFilter($event); $this->Authentication->allowUnauthenticated(['create', 'search']); } }
試したこと
エラーの内容としてはCSRFが無効化されていない状態のようだったので、
Application.phpの中のif文を$request->getParam('controller') === 'Forms'
に変更するなど
してみましたが、同様のエラーが出て回避はできませんでした。
補足情報(FW/ツールのバージョンなど)
※各種バージョン情報※
CakePHPバージョン:4.2.8
PHPバージョン:7.4.16
開発環境:MAMP 6.4
※参考サイト※
・CakePHP 4.x Strawberry Cookbook CMS チュートリアル - 認証
・CakePHP 4.x Strawberry Cookbook クロスサイトリクエストフォージェリー (CSRF) ミドルウェア
・CakePHP4 で簡単な API を作る
・CakePHP 4 で CSRF 保護を一部または完全に無効化(有効化)する方法
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。