将 TinyMCE 图片上传与 CakePHP 3.8 集成时出现 CSRF 问题

CSRF issues when integrating TinyMCE image upload with CakePHP 3.8

我正在使用 CakePHP 3.8 为网站创建 CMS。我需要一个简单的所见即所得的图片上传编辑器。我以前使用过 CKEditor,但在上传图片时遇到问题,所以我想试试 TinyMCE。

因此,我下载了 TinyMCE 5(带有所有标准插件),将其链接到我页面的头部,并创建了一个带有 TinyMCE 文本区域的表单,如下所示:

<fieldset>
    <legend>New Page</legend>
    <?php
        echo $this->Flash->render();
        echo $this->Form->create($newpage);
        echo $this->Form->control('title');
        echo $this->Form->control('content', 
                      array('label' => 'Page Content',
                            'type' => 'textarea', 
                            'id' => 'editor_area'));
        echo $this->Form->button('Save');
        echo $this->Form->end();
    ?>
</fieldset>

<script>
    tinymce.init({
        selector:'#editor_area',
        height: 500,
        menubar: false,
        images_upload_url: '<?php echo IMG_UPLOAD_URL ?>',
        toolbar: [
            'undo redo | cut copy paste | styleselect | bold italic underline removeformat | alignleft aligncenter alignright | charmap | bullist numlist | link image'
        ],
        plugins: ['advlist lists link autolink image charmap imagetools code']
    });
</script>

这工作正常,文本区域与编辑器等一起出现。images_upload_url 中的上传 url 指向以下 UploadsController.php(为简洁起见,我省略了细节;如果需要可以添加它们):

<?php
namespace App\Controller\Admin;

use App\Controller\AppController;

class UploadsController extends AppController
{

    public function uploadImage() {

        $result = array();
        $result['success'] = 'success';

        // Process file upload

        return $this->response->withType('application/json')
                    ->withStringBody(json_encode($result));

    }

}

当我上传图片时,控制台出现以下错误:

Failed to load resource: the server responded with a status of 403 (Forbidden) 

CakePHP 的输出显示错误:

Error: CSRF token mismatch.

调试器显示 POST 包括以下内容:

Cookie: CAKEPHP=dvsktjv7vp8la5nv7dv19634d1; csrfToken=53e5718e13a1e963d51f9c93c48471a478b35c02b565d6f0699cd2a335775c2b17986cfc2cc587ff7343a6573e3eb2e498a9cb962397599c023417d1dfa9506c; ckCsrfToken=7l2PEC0g06819qQcLwdX5ul7E7jNRa3r61jENt2x

我不知道从这里到哪里去。

(或者,如果有更直接的方法来包含一个 free/inexpensive 所见即所得的编辑器和一个体面的 image/file 上传器,我愿意接受建议!这是一个学校网站,所以预算是非常小,不可能是每月费用。)

cookie数据只是CSRF保护机制的一部分,客户端需要在请求数据或X-CSRF-Token header中发送CSRF token。

我不太熟悉 TinyMCE 图片上传,但查看文档,您可能需要一个自定义上传处理程序,您可以在其中添加其他数据,即 CSRF 令牌。

the example from the TinyMCE docs 为例,处理程序可能看起来像这样,其中 CSRF 令牌附加到表单数据:

images_upload_handler: function (blobInfo, success, failure) {
    var xhr, formData;

    xhr = new XMLHttpRequest();
    xhr.withCredentials = false;
    xhr.open('POST', <?= json_encode(IMG_UPLOAD_URL) ?>);

    xhr.onload = function() {
        var json;

        if (xhr.status != 200) {
            failure('HTTP Error: ' + xhr.status);
            return;
        }

        json = JSON.parse(xhr.responseText);

        if (!json || typeof json.location != 'string') {
            failure('Invalid JSON: ' + xhr.responseText);
            return;
        }

        success(json.location);
    };

    formData = new FormData();
    formData.append('file', blobInfo.blob(), blobInfo.filename());
    // append CSRF token in the form data
    formData.append('_csrfToken', <?= json_encode($this->request->getParam('_csrfToken')) ?>);

    xhr.send(formData);
}

此外,根据文档,响应 JSON 必须包含名为 location 的 属性,其中包含上传文件的 Web 路径,该路径可能在您的代码中已经遗漏了,提一下以防万一。

另见