Почему на запросы AJAX запускается ответ 400, несмотря на разблокировку действий с помощью компонента безопасности? - PullRequest
0 голосов
/ 17 июня 2020

Я пытаюсь получить запрос ajax, работающий в CakePHP4, но продолжаю работать с защитой CSRF.

В моем контроллере:

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

        $this->Security->setConfig('unlockedActions', ['players']);
    }

public function players()
    {
        $players = ['Sjaak Afhaak', 'Aad Kippezaad', 'Gras Kaffer', 'Tedje van Es'];

        if ($this->request->is('ajax')) {
            $this->response = $this->response->withDisabledCache();
        }

        $letter = trim($this->request->getData('letter'));
        if (!empty($letter)) {
            $players = array_filter($spelers, function ($haystack) use ($letter) {
                return(strpos($haystack, $letter));
            });
        }

        $this->set(compact('players'));
        $this->viewBuilder()->setOption('serialize', ['players']);

        $this->RequestHandler->renderAs($this, 'json');
    }

Затем в файле шаблона :

<?php echo $this->Html->script('jquery.min'); ?>

<div class="container">
    <div class="row">
        <div class="column">
            <div class="users form content">
                <?php echo $this->Form->create(null, ['url' => \Cake\Routing\Router::pathUrl('Ado::players')]); ?>
                <fieldset>
                    <legend>Players</legend>
                    <?php echo $this->Form->text('letter', ['placeholder' => 'Begin letter(s)']); ?>
                </fieldset>
                <?= $this->Form->button('OK'); ?>
                <?= $this->Form->end() ?>
            </div>
        </div>
        <div class="column response">
            ...
        </div>
    </div>
</div>

<script>
    $(document).ready(function () {
        $(document).on("submit", "form", function (event) {
            var $form = $(this);
            var $target = $('div.response');
            var csrf = $('input[name=_csrfToken]', $form).val();
            var data = { letter:  $('input[name=letter]', $form).val() };

            $target.html('');

            $.ajax({
                method: "POST",
                url: $form.attr('action'),
                beforeSend: function(xhr) {
                    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                    xhr.setRequestHeader('X-CSRF-Token', csrf);
                },
                data: data,
                dataType: "json"
            })
                .done(function (response) {
                    var items = [];
                    $.each( response, function( key, val ) {
                        items.push( "<li id='" + key + "'>" + val + "</li>" );
                    });

                    $( "<ul/>", {
                        "class": "spelers-list",
                        html: items.join( "" )
                    }).appendTo( $target );
                });

            event.preventDefault();
        });
    });
</script>

Без beforeSend в вызове ajax я получаю ответ 403. Если я включаю X-CSRF-Token, я получаю ответ 400.

2020-06-18 09:49:38 Error: [Cake\Http\Exception\BadRequestException] `_Token` was not found in request data. in src\vendor\cakephp\cakephp\src\Controller\Component\FormProtectionComponent.php on line 143
Stack Trace:
- src\vendor\cakephp\cakephp\src\Controller\Component\FormProtectionComponent.php:97
- src\vendor\cakephp\cakephp\src\Event\EventManager.php:309
- src\vendor\cakephp\cakephp\src\Event\EventManager.php:286
- src\vendor\cakephp\cakephp\src\Event\EventDispatcherTrait.php:92
- src\vendor\cakephp\cakephp\src\Controller\Controller.php:569
- src\vendor\cakephp\cakephp\src\Controller\ControllerFactory.php:72
- src\vendor\cakephp\cakephp\src\Http\BaseApplication.php:229
- src\vendor\cakephp\cakephp\src\Http\Runner.php:77
- src\vendor\cakephp\cakephp\src\Http\Middleware\BodyParserMiddleware.php:164
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\authorization\src\Middleware\AuthorizationMiddleware.php:129
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\authentication\src\Middleware\AuthenticationMiddleware.php:124
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Http\Runner.php:77
- src\vendor\cakephp\cakephp\src\Http\Middleware\CsrfProtectionMiddleware.php:138
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Http\Runner.php:58
- src\vendor\cakephp\cakephp\src\Routing\Middleware\RoutingMiddleware.php:166
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Routing\Middleware\AssetMiddleware.php:68
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Error\Middleware\ErrorHandlerMiddleware.php:119
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\debug_kit\src\Middleware\DebugKitMiddleware.php:60
- src\vendor\cakephp\cakephp\src\Http\Runner.php:73
- src\vendor\cakephp\cakephp\src\Http\Runner.php:58
- src\vendor\cakephp\cakephp\src\Http\Server.php:90
- src\webroot\index.php:41

Не уверен, связано ли это, но я использую плагин аутентификации. (https://book.cakephp.org/authentication/2/en/index.html)

1 Ответ

1 голос
/ 19 июня 2020

Как видно из трассировки стека, ошибка возникает из-за компонента защиты формы , а не из компонента безопасности, поэтому действия по разблокировке компонента безопасности ничего не сделают.

Компонент безопасности устарел (похоже, в Поваренной книге это не упоминается), а компонент защиты формы - одна из утилит, которые его заменяют (другие - CSRF промежуточное ПО и промежуточное ПО для обеспечения HTTPS ) - вы не должны использовать оба, удалите компонент безопасности (и под этим я подразумеваю также удалить связанный loadComponent() call), и вместо этого настройте компонент защиты формы соответственно! t указан в разделе компонентов.

...