Cakephp PHP WEB開発

[Cakephp3]AJAXでCSRFトークンを埋める(CSRF token mismatch エラー回避)

※本サイトはPR表記を含みます。

WEBアプリケーションのセキュリティの一つとしてCSRF対策(CSRFの詳細についはIPAを参照)が挙げられます。CakephpではCSRFコンポーネントを利用するのが通常でしょう。

そこで必要になるのが CSRFトークン。単にajaxを利用しようとすると、「CSRF token mismatch」エラーが発生します。そして、バージョンによる差異はあるかもですが、SecurityComponetエラーも発生。([Cake\Controller\Exception\AuthSecurityException] '_Token' was not found in request data.)エラー内容: リクエストデータにトークンがありまへんで

Cakephp は Formヘルパーを利用し、$this->Form->create() すれば、自動でCSRFトークンを生成してくれます。よって、通常のフォーム作成ではFormヘルパーさえ活用していれば、CSRF対策を特に気にしてなくもOK。(CSRFコンポーネントは有効であること)

以下、AJAXの場合のCSRFトークンの利用法です。

step
1
FormヘルパーでCSRFトークンを自動生成して利用

<?php // CSRFトークン発行(AJAXで利用) ?>
<?= $this->Form->create(null) ?>
<?= $this->Form->end() ?>

これでChromeなどで右クリック「検証」でコードを確認すると、「_csrfToken」という形でCSRFトークンが自動生成されているのを確認できます。

 

step
2
AJAXのbeforeSendでトークンセット

<script>
$(function(){
    $('要素名指定').on('click', function() {
      // Formヘルパーで生成したCSRFトークンの値を取得
      var csrf = $('input[name=_csrfToken]').val();
        $.ajax({
            type: 'POST',
            url: '<?= $this->Url->build(['controller' => 'コントローラ名', 'action' => 'アクション名']) ?>',
            data: 送信したいjsonデータとか,
            // ここが本丸。CSRFトークンをセット
            beforeSend: function(xhr) {
                 xhr.setRequestHeader('X-CSRF-Token', csrf);
            },
        }).done(function(data) {
            // 成功時処理
        }).fail(function() {
            // 失敗時処理
        });
    });
});
</script>

AJAXで送信する時、beforeSendでリクエストヘッダーに「X-CSRF-Token」としてトークンをセットしておきます。

 

step
3
AJAXのurl先コントローラーでセキュリティアクションのajax許可

public function beforeFilter(Event $event)
{
    parent::beforeFilter($event);

    $this->Security->setConfig('unlockedActions', ['許可したいアクション名']);
}

Securityコンポーネントは親コントローラーAppControllerでロードしておくこと(initialize()内、$this->loadComponent('Security');

これで通過できるようになります。

 

AJAX通信確認方法:

ChromeのF12キーでDevelopmentToolsを起動し、「Network」タブの「Fetch/XHR」が選択されている状態で画面をリロードし、AJAXアクションが発生する箇所をクリックするなどすれば200(成功)レスポンスが確認できるはず。

 

・Securityコンポーネント(CSRF)
https://book.cakephp.org/3/ja/controllers/components/security.html#csrf

・非推奨だけどCSRF無効
https://book.cakephp.org/3/ja/controllers/components/csrf.html

・CSRF対策(クロスサイトリクエストフォージェリ)について

https://www.ipa.go.jp/security/vuln/websecurity-HTML-1_6.html

-Cakephp, PHP, WEB開発
-