将TinyMCE图像上传与CakePHP 3.8集成时的CSRF问题

时间:2019-10-29 13:08:24

标签: cakephp tinymce cakephp-3.0 csrf

我正在使用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

我不确定从这里去哪里。

(或者,如果有更直接的方法来包含免费/廉价的所见即所得编辑器以及不错的图像/文件上传器,我欢迎您提出建议!这是一所学校的网站,因此预算非常小且无法是每月费用。)

1 个答案:

答案 0 :(得分:1)

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

我对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路径,该属性可能在您省略的代码中,以防万一。

另请参见