【问题标题】:CakePHP 3: Forbidden Error when sending Ajax Post request of jQuery-TableditCakePHP 3:发送 jQuery-Tabledit 的 Ajax Post 请求时出现禁止错误
【发布时间】:2019-10-04 10:01:39
【问题描述】:

尝试在我的表上实现 jQuery-Tabledit (https://markcell.github.io/jquery-tabledit/) 时出现 403 Forbidden Error。经过研究,问题似乎与授权有关,但我不知道如何解决。我既不使用 AuthComponent 也不使用 SecurityComponent。

模板/用户/index.ctp

<div class="user index large-9 medium-8 columns content">
    <h3><?= __('User') ?></h3>
    <table id="table" cellpadding="0" cellspacing="0">
        <thead>
            <tr>
                <th scope="col">Id</th>
                <th scope="col">Name</th>
                <th scope="col">Email</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($user as $user): ?>
            <tr>
                <td><?= $this->Number->format($user->id) ?></td>
                <td><?= h($user->name) ?></td>
                <td><?= h($user->email) ?></td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>

<?= $this->Html->script('/js/table_edit_test') ?>

webroot/js/table_edit_test.js

$(document).ready(function(){
    $('#table').Tabledit({
        url:"/user/testing",
        columns: {
            identifier: [0, 'id'],
            editable: [[1, 'name'], 
            [2, 'email']]
        },

        onSuccess: function(data, textStatus, jqXHR) {
            console.log('onSuccess(data, textStatus, jqXHR)');
            console.log(data);
            console.log(textStatus);
            console.log(jqXHR);
        },

        onFail: function(jqXHR, textStatus, errorThrown) {
            console.log('onFail(jqXHR, textStatus, errorThrown)');
            console.log(jqXHR);
            console.log(textStatus);
            console.log(errorThrown);
        },

        onAjax: function(action, serialize) {
            console.log('onAjax(action, serialize)');
            console.log(action);
            console.log(serialize);
        },
    });
});

UserController.php

public function index() {
    $user = $this->paginate($this->User);

    $this->set(compact('user'));
}

public function testing() {
    $this->autoRender = false;
    if($this->request->is('Ajax')) {
        $input = filter_input_array(INPUT_POST);

        if($input["action"] === 'edit') {
            $user = $this->User->get($input["id"]);
            $user->name = $input["name"];
            $user->email = $input["email"];
            $this->User->save($user);
        }

        return json_encode($input);
    }
}

AppController.php

public function initialize() {
    parent::initialize();

    $this->loadComponent('RequestHandler', [
        'enableBeforeRedirect' => false,
    ]);
    $this->loadComponent('Flash');

    /*
     * Enable the following component for recommended CakePHP security settings.
     * see https://book.cakephp.org/3.0/en/controllers/components/security.html
     */
    //$this->loadComponent('Security');
}

调试截图:

任何帮助将不胜感激。

【问题讨论】:

  • 你的控制器应该返回一个响应对象,而不是文本。 return json_encode($input); 应该是 return $this-&gt;response-&gt;withStringBody(json_encode($input));
  • 关于 403 有一些可能性。关于 CSRF,您需要考虑一件事。 cakephp 3 更安全,并遵循现代 PHP。你应该尝试X-CSRF-Token 喜欢headers : {'X-CSRF-Token': $('[name="_csrfToken"]').val()},
  • @GregSchmidt 已经解决了这个问题。不幸的是,403 错误仍然存​​在。
  • @502_Geek 我已经确认:这绝对是 CSRF 的原因。我正在测试各种 CSRF 标头方法,其中一种可以工作......可能 5 秒。重新加载页面后它不再起作用,如果我的数据库中没有明确的变化,我会认为这是一个梦想。我目前经历了大约 7 个打开的标签,将我的代码改回来并希望再次找到那个魔法。我的嫌疑人是 jquery.tabledit.js 中的代码var jqXHR = $.post(settings.url, serialize, function(data, textStatus, jqXHR) { //some function }, 'json');
  • 不成功的尝试:在 $.post() 之前写了$.ajaxSetup({ headers: { 'X-CSRF-Token': $('[name="_csrfToken"]').val() } });;写了var jqXHR = $.post(settings.url, $('[name="_csrfToken"]').val(), serialize, function(data, textStatus, jqXHR) { //some function }, 'json');;在 table_edit_test.js 中:写了beforeSend: function (xhr) { xhr.setRequestHeader(‘X-CSRF-Token’, $('[name="_csrfToken"]').val()); },;方法同上,但将$('[name="_csrfToken"]').val()改为&lt;?= json_encode($this-&gt;request-&gt;getParam('_csrfToken')); ?&gt;(产生错误)

标签: javascript jquery ajax cakephp cakephp-3.0


【解决方案1】:

403 错误来自 CSRF-Token,即使您没有选择使用该组件,它也会在 CakePHP 3.6 及更高版本中自动添加。感谢 502_Geek 帮助我找出原因。我的解决方法:

  • src/Template/Layout/default.ctp中:添加标题
<head>
<!--Get CSRF-Token -->
<meta name="csrf-token" content="<?= $this->request->getParam('_csrfToken') ?>" />
</head>
  • webroot/js/jquery.tabledit.js 中:将 $.post() 更改为 $.ajax() 并将 CSRF-Token 添加到 header:
var jqXHR = $.ajax({
    type: "POST",
    url: settings.url,
    headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
    data: serialize,
    success: function(data, textStatus, jqXHR) {

        if (action === settings.buttons.edit.action) {
            $lastEditedRow.removeClass(settings.dangerClass).addClass(settings.warningClass);
            setTimeout(function() {
                //$lastEditedRow.removeClass(settings.warningClass);
                $table.find('tr.' + settings.warningClass).removeClass(settings.warningClass);
            }, 1400);
        }

        settings.onSuccess(data, textStatus, jqXHR);
    },
    dataType: 'json'
});
  • webroot/js/table_edit_test.js 中:为 URL 使用完整链接:
url: 'https://localhost/user/testing',

任何像我一样开始学习 JavaScript 的新手的注意事项:

  • F12 -> 控制台:读取 console.log()
  • F12 -> 网络 -> 单击有错误状态的文件 -> 参数:从 Ajax 读取 $_POST
  • F12 -> 网络 -> 点击有错误状态的文件 -> 响应:读取错误的主要原因(CSRF 不匹配,找不到对象等)

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 2013-10-20
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    相关资源
    最近更新 更多