This document is for CakePHP's development version, which can be significantly different from previous releases.
You may want to read current stable release documentation instead.

CSRFプロテクション

クロスサイトリクエストフォージェリ(CSRF)は、 認証されたユーザーの知らないうちに同意なしに 不正なコマンドが実行される エクスプロイト(攻撃手法)の一種です

CakePHPは、2つの形式のCSRFプロテクションを提供します。:

  • SessionCsrfProtectionMiddleware は、CSRFトークンをセッションに保存します。 このため、side-effects(「副作用」と訳されますが、コンピューティング用語としては、 想定外の動作を起こす可能性を持つあらゆる処理を意味します。エクスプロイトはこれを悪用します)を持つ すべてのリクエストでセッションを開く必要があります。 セッションベースのCSRFトークンの利点は、 それらが特定のユーザーにスコープされ、 セッションが有効である間のみ有効であるということです。

  • CsrfProtectionMiddleware はCSRFトークンをクッキーに保存します。 クッキー values クッキーを使用すると、サーバー上にstateがなくてもCSRFチェックを実行できます。 クッキーの値は、HMACチェックを使用して信頼性が検証されます。 ただし、ステートレスであるため、CSRFトークンはユーザーとセッション間で再利用できます。

注釈

両方のアプローチを同時に使用することはできません。 ひとつだけを選択する必要があります。両方のアプローチを同時に使用すると、 すべての PUT および POST リクエストでCSRFトークンの不一致エラーが発生します。

CSRFミドルウェア(クロスサイトリクエストフォージェリミドルウェア)

CSRFプロテクションは、アプリケーション全体、または特定のルーティングスコープに 適用できます。CSRFミドルウェアをアプリケーションミドルウェアスタックに 適用することで、アプリケーション内のすべてのアクションを保護できます。:

// src/Application.php
// クッキーベースの CSRF トークンの場合
use Cake\Http\Middleware\CsrfProtectionMiddleware;

// セッションベースの CSRF トークンの場合
use Cake\Http\Middleware\SessionCsrfProtectionMiddleware;

public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
    $options = [
        // ...
    ];
    $csrf = new CsrfProtectionMiddleware($options);
    // または
    $csrf = new SessionCsrfProtectionMiddleware($options);

    $middlewareQueue->add($csrf);

    return $middlewareQueue;
}

ルーティングスコープにCSRF保護を適用することにより、CSRFを特定のルートグループに条件付きで適用できます。:

// src/Application.php
use Cake\Http\Middleware\CsrfProtectionMiddleware;

public function routes(RouteBuilder $routes) : void
{
    $options = [
        // ...
    ];
    $routes->registerMiddleware('csrf', new CsrfProtectionMiddleware($options));
    parent::routes($routes);
}

// config/routes.php
$routes->scope('/', function (RouteBuilder $routes) {
    $routes->applyMiddleware('csrf');
});

CookieベースのCSRFミドルウェアオプション

使用可能なオプションは次のとおりです。

  • cookieName 送信するクッキーの名前。デフォルトは csrfToken

  • expiry CSRFトークンの存続期間。デフォルトはブラウザセッションです。

  • secure クッキーがSecureフラグで設定されるかどうか。 つまりHTTPS接続が有効なアプリの場合のみ設定されるため、 HTTP接続の場合は失敗します。デフォルトは false です。

  • httponly クッキーがHttpOnlyフラグで設定されるかどうか。 デフォルトは false です。4.1.0より前では、このhttpOnlyオプションを使用してください。

  • samesite クッキーをファーストパーティまたは同じサイトのコンテキストに 制限する必要があるかどうかを宣言できます。 可能な値は LaxStrictNone で、デフォルトは null です。

  • field チェックするフォームフィールド。デフォルトは _csrfToken 。 これを変更するには、FormHelperの構成も必要になります。

セッションベースのCSRFミドルウェアオプション

使用可能なオプションは次のとおりです。

  • key 使用するセッションキー。デフォルトは csrfToken です。

  • field チェックするフォームフィールド。これを変更するには、FormHelperの構成も必要になります。

有効にすると、リクエストオブジェクトのCSRFトークンを取得できます。:

$token = $this->request->getAttribute('csrfToken');

特定のアクションのCSRFチェックをスキップする

どちらのCSRFミドルウェア実装でも、 チェックコールバック機能をスキップして、 CSRFトークンチェックを実行する必要があるURLを よりきめ細かく制御できます。:

// src/Application.php
use Cake\Http\Middleware\CsrfProtectionMiddleware;

public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
    $csrf = new CsrfProtectionMiddleware();

    // コールバックが `true`を返す場合、トークンチェックはスキップされます。
    $csrf->skipCheckCallback(function ($request) {
        // Skip token check for API URLs.
        if ($request->getParam('prefix') === 'Api') {
            return true;
        }
    });

    // CSRF保護ミドルウェアの前にルーティングミドルウェアがキューに追加されていることを確認してください。
    $middlewareQueue->add($csrf);

    return $middlewareQueue;
}

注釈

CSRFプロテクションミドルウェアは、クッキーまたはセッションを使用して ステートフルリクエストを処理するルートにのみ適用する必要があります。 たとえば、APIを開発する場合、認証にクッキーを使用しないステートレスリクエストは CSRFの影響を受けないため、これらのルートにミドルウェアを適用する必要はありません。

フォームヘルパーとの統合

CSRFプロテクションミドルウェアフォームヘルパー とシームレスに統合されます。 フォームヘルパーを使用して作成したフォームを生成するたびに、CSRFトークンを持つ hiddenフィールドが挿入されます。

注釈

CSRFプロテクションを使用する場合は フォームヘルパー でフォームを作成する必要があります。 そうでない場合は、hiddenフィールドを手動してください。

CSRFプロテクションとAJAXリクエスト

リクエストデータパラメータに加えて、CSRFトークンは 特別な X-CSRF-Token ヘッダーを介して送信できます。 多くの場合、ヘッダーを使用すると、CSRFトークンを 重めのJavaScriptのアプリケーションまたは XML / JSONベースのAPIエンドポイントと簡単に統合できます。

CSRFトークンは、JavaScriptでは csrfToken クッキーを介して、 PHPでは csrfToken という名前のリクエストオブジェクト属性を 介して取得できます。 JavaScriptコードがCakePHPビューテンプレートとは別のファイルにある場合、 およびJavaScriptを介してクッキーを解析する機能がすでにある場合は、 クッキーの使用が簡単になる可能性があります。

個別のJavaScriptファイルがあるが、クッキーの処理をしたくない場合は、 たとえば、次のようなスクリプトブロックを定義することにより、 レイアウトのグローバルJavaScript変数にトークンを設定できます。:

echo $this->Html->scriptBlock(sprintf(
    'var csrfToken = %s;',
    json_encode($this->request->getAttribute('csrfToken'))
));

次に、このスクリプトブロックの後にロードされる任意のスクリプトファイルで、 csrfToken または window.csrfToken としてトークンに アクセスできます。

metaタグにトークンを設定する方法もあります。:

echo $this->Html->meta('csrfToken', $this->request->getAttribute('csrfToken'));

csrfToken という名前の metaタグ を探すことでスクリプトからアクセスできます。 jQueryを使用する場合と同じくらい簡単で

var csrfToken = $('meta[name="csrfToken"]').attr('content');