🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

解決済

1回答

3672閲覧

cakephp公式チュートリアル:cms Missing or invalid CSRF cookie.

YuhiUsui

総合スコア11

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

0グッド

0クリップ

投稿2020/11/27 04:23

編集2020/11/27 13:43

前提・実現したいこと

初学習者です

公式チュートリアル
記事の管理アプリについてですが、記事の新規作成と編集、タグの新規作成と編集の際にエラーが発生しています。

発生している問題・エラーメッセージ

bakeコマンドで作成したコード。Formヘルパーを使用してadd/editを作成しているのに下記のエラーがでる

Missing or invalid CSRF cookie. if (!$this->_verifyToken($cookie)) { $exception = new InvalidCsrfTokenException(__d('cake', 'Missing or invalid CSRF cookie.')); $expiredCookie = $this->_createCookie('', $request)->withExpired(); $exception->responseHeader('Set-Cookie', $expiredCookie->toHeaderValue());

該当のソースコード

src/application.php

<?php declare(strict_types=1); /** * CakePHP(tm) : Rapid Development Framework (https://cakephp.org) * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) * @link https://cakephp.org CakePHP(tm) Project * @since 3.3.0 * @license https://opensource.org/licenses/mit-license.php MIT License */ namespace App; use Cake\Core\Configure; use Cake\Core\Exception\MissingPluginException; use Cake\Error\Middleware\ErrorHandlerMiddleware; use Cake\Http\BaseApplication; use Cake\Http\Middleware\BodyParserMiddleware; use Cake\Http\Middleware\CsrfProtectionMiddleware; use Cake\Http\MiddlewareQueue; use Cake\Routing\Middleware\AssetMiddleware; use Cake\Routing\Middleware\RoutingMiddleware; // use Cake\Network\Exception\InvalidCsrfTokenException; // use Authentication\AuthenticationService; // use Authentication\AuthenticationServiceInterface; // use Authentication\AuthenticationServiceProviderInterface; // use Authentication\Middleware\AuthenticationMiddleware; // use Psr\Http\Message\ServerRequestInterface; /** * Application setup class. * * This defines the bootstrapping logic and middleware layers you * want to use in your application. */ class Application extends BaseApplication // implements AuthenticationServiceProviderInterface { /** * Load all the application configuration and bootstrap logic. * * @return void */ public function bootstrap(): void { $this->addPlugin('Migrations'); // Call parent to load bootstrap from files. parent::bootstrap(); if (PHP_SAPI === 'cli') { $this->bootstrapCli(); } /* * Only try to load DebugKit in development mode * Debug Kit should not be installed on a production system */ if (Configure::read('debug')) { $this->addPlugin('DebugKit'); } // Load more plugins here } /** * Setup the middleware queue your application will use. * * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup. * @return \Cake\Http\MiddlewareQueue The updated middleware queue. */ 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, ])); return $middlewareQueue; } /** * Bootstrapping for CLI application. * * That is when running commands. * * @return void */ protected function bootstrapCli(): void { try { $this->addPlugin('Bake'); } catch (MissingPluginException $e) { // Do not halt if the plugin is missing } $this->addPlugin('Migrations'); // Load more plugins here } // public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue // { // $middlewareQueue // // ... 前に追加された他のミドルウェア // ->add(new RoutingMiddleware($this)) // // RoutingMiddleware の後に認証を追加 // ->add(new AuthenticationMiddleware($this)); // return $middlewareQueue; // } // public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface // { // $authenticationService = new AuthenticationService([ // 'unauthenticatedRedirect' => '/users/login', // 'queryParam' => 'redirect', // ]); // // identifiers を読み込み、email と password のフィールドを確認します // $authenticationService->loadIdentifier('Authentication.Password', [ // 'fields' => [ // 'username' => 'email', // 'password' => 'password', // ] // ]); // // authenticatorsをロードしたら, 最初にセッションが必要です // $authenticationService->loadAuthenticator('Authentication.Session'); // // 入力した email と password をチェックする為のフォームデータを設定します // $authenticationService->loadAuthenticator('Authentication.Form', [ // 'fields' => [ // 'username' => 'email', // 'password' => 'password', // ], // 'loginUrl' => '/users/login', // ]); // return $authenticationService; // } }

記事作成

php

1<h1>記事の追加</h1> 2<?php 3 echo $this->Form->create($article); 4 echo $this->Form->control('user_id', ['type' => 'hidden', 'value' => 1]); 5 echo $this->Form->control('title'); 6 echo $this->Form->control('body', ['rows'=>'3']); 7 echo $this->Form->control('tags._ids', ['options' => $tags]); 8 echo $this->Form->button(__('Save Article')); 9 echo $this->Form->end(); 10?>

記事編集

<h1>記事の編集</h1> <?php echo $this->Form->create($article); echo $this->Form->control('user_id', ['type'=>'hidden']); echo $this->Form->control('title'); echo $this->Form->control('body', ['row'=>'3']); echo $this->Form->control('tag_string', ['type' => 'text']); echo $this->Form->button(__('Save Article')); echo $this->Form->end(); ?>

タグ作成

<?php /** * @var \App\View\AppView $this * @var \App\Model\Entity\Tag $tag */ ?> <div class="row"> <aside class="column"> <div class="side-nav"> <h4 class="heading"><?= __('Actions') ?></h4> <?= $this->Html->link(__('List Tags'), ['action' => 'index'], ['class' => 'side-nav-item']) ?> </div> </aside> <div class="column-responsive column-80"> <div class="tags form content"> <?= $this->Form->create($tag) ?> <fieldset> <legend><?= __('Add Tag') ?></legend> <?php echo $this->Form->control('title'); echo $this->Form->control('articles._ids', ['options' => $articles]); ?> </fieldset> <?= $this->Form->button(__('Submit')) ?> <?= $this->Form->end() ?> </div> </div> </div>

タグ編集

<?php /** * @var \App\View\AppView $this * @var \App\Model\Entity\Tag $tag */ ?> <div class="row"> <aside class="column"> <div class="side-nav"> <h4 class="heading"><?= __('Actions') ?></h4> <?= $this->Form->postLink( __('Delete'), ['action' => 'delete', $tag->id], ['confirm' => __('Are you sure you want to delete # {0}?', $tag->id), 'class' => 'side-nav-item'] ) ?> <?= $this->Html->link(__('List Tags'), ['action' => 'index'], ['class' => 'side-nav-item']) ?> </div> </aside> <div class="column-responsive column-80"> <div class="tags form content"> <?= $this->Form->create($tag) ?> <fieldset> <legend><?= __('Edit Tag') ?></legend> <?php echo $this->Form->control('title'); echo $this->Form->control('articles._ids', ['options' => $articles]); ?> </fieldset> <?= $this->Form->button(__('Submit')) ?> <?= $this->Form->end() ?> </div> </div> </div>

試したこと

別のteratail質問参照
https://teratail.com/questions/165237

イメージ説明
CSRF cookie

補足情報(FW/ツールのバージョンなど)

cake4, php7.4, xamppVM

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nojimage

2020/11/27 13:18

フォームを表示したときに、Cookieに csrfToken がセットされていますか? ブラウザの開発者ツールなどで確認してみてください。(DebugKitを入れているならRequestパネルでの確認でも良いです。
nojimage

2020/11/27 13:22 編集

src/Application.phpの内容はすべて提示していないように見えます。可能であればすべて提示してください。
YuhiUsui

2020/11/27 13:44

いつもありがとうございます!!! 指摘された点追加完了したので確認いただければ幸いです!
nojimage

2020/11/30 23:40

もしかして、CsrfProtectionMiddlewareの多重登録をしていませんか?config/routes.phpでも登録しているなら、src/Application.phpでの登録は不要です。
YuhiUsui

2020/12/03 03:20

その辺りはいじっていなく確認しましたが、routes.phpに登録してないと思います。
nojimage

2020/12/04 00:56

提示してもらった限りでは、CookieのcsrfTokenとPOSTのcsrfTokenは一致しているようなので原因が判りませんね…あとはXDebugでブレークしながらトークンの検証を行っている部分のコードを追っていくしか解決方法を見つけれなさそうです。
YuhiUsui

2020/12/04 07:07

nojimageさんいつもありがとうございます。 ちょっと地道にやってみます!!
guest

回答1

0

ベストアンサー

エラーメッセージは、例外処理のメッセージそのままですね。

CSRF処理を行っているのがコンポネントなのか、ミドルウェアなのかどっちでしょうか。ミドルウェアを呼び出して、コンポネントで例外処理を出せば、そりゃ例外処理が出る気がします。

PHP

1Cake\Http\Middleware\CsrfProtectionMiddleware; //呼び出しているのはミドルウェア 2//Cake\Network\Exception\InvalidCsrfTokenException; //こっちは呼び出しされていない
if (!$this->_verifyToken($cookie)) { //ミドルウェアを使っているのにコンポネントで判定しようとしている $exception = new InvalidCsrfTokenException(__d('cake', 'Missing or invalid CSRF cookie.')); $expiredCookie = $this->_createCookie('', $request)->withExpired(); $exception->responseHeader('Set-Cookie', $expiredCookie->toHeaderValue());

ちなみにCakePHP4ではミドルウェア使用推奨になってるみたいですね。

投稿2020/11/27 09:26

編集2020/11/27 16:10
FKM

総合スコア3647

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YuhiUsui

2020/11/27 10:12

回答ありがとうございます 指摘していただいた内容は薄らですが理解できました! チュートリアル 通りに実行しているので規格外の動きをするのがしっくりこないのですが、 どのようにしてcsrf処理の仕様を変更するのでしょうか? 試しにミドルウェアのuse文をake\Network\Exception\InvalidCsrfTokenException;に変えてみたのですが、Cake\Http\Middleware\CsrfProtectionMiddleware;が無いよと言われてしまいまして。。
nojimage

2020/11/27 13:25

チュートリアル通りに進めているのであれば、コンポーネントではなくミドルウェアでCSRF処理を行っているはずです。
FKM

2020/11/30 02:55 編集

Railsとか使用したことあればピンとくると思いますが、cakePHPはRailsのインスパイアです。なので、useでミドルウェアを呼び出すときは、使いたいものをuse文で呼び出す必要があります。 そして、当然Controllerの中でメソッドを呼び出すのも、そのミドルウェアに関連したものです。肝心のCsrfProtectionMiddlewareの呼び出しを別のミドルウェアに上書きしたりしてませんか? 簡潔に言えば、CSRFを制御する二種類の方法がごちゃまぜになっている気がします。
YuhiUsui

2020/12/03 03:23

ご説明いただきありがとうございます 内容理解できましたが私の方で上書きのような処理はしたことが無いと記憶しています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問