如何在 CKeditor 上传中向 POST 值添加字段
Posted
技术标签:
【中文标题】如何在 CKeditor 上传中向 POST 值添加字段【英文标题】:How to add a field to POST values in CKeditor upload 【发布时间】:2012-05-10 16:16:16 【问题描述】:我使用 django 和 ckeditor 为 TextEdits 提供所见即所得的体验。我想使用CKEditor文件上传功能(在文件浏览器/图像对话框中),但是CKEditor上传图像的POST只包含文件数据。
这是 CSRF 检查的问题。我无法在 CKEditor 文档中找到一个位置来更改文件上传的 POST 数据,以在 POST 数据中添加 django 的 csrf_token。
作为一种解决方法,我可以更改 filebrowserUploadUrl 参数以在上传 URL 中包含 csrf 数据,对上传视图使用 @csrf_exempt,并检查 request.GET 参数以检查 csrf。但是这个解决方案安全吗?
无论如何,如果有人知道如何在 CKEditor 文件上传 POST 数据中直接包含 csrf 令牌,我非常感兴趣...
【问题讨论】:
您使用的是django-ckeditor 还是其他小部件?如果您是自己编写的 - 这是正确的,您不能在 POST 中添加内容,因为发布的正文就是文件本身。所以是的,您需要在 url 参数中提供令牌。 甚至 django-ckeditor 也不对文件上传使用 csrf 保护(恕我直言,这很糟糕):@csrf_exempt def upload(request): """ 上传文件并将其 URL 发送回 CKEditor。 TODO:验证上传“”“ 【参考方案1】:你可以注册dialogDefinition事件,完全重写上传标签,这样:
CKEDITOR.on('dialogDefinition', function (ev)
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if (dialogName == 'image')
dialogDefinition.removeContents('Upload');
dialogDefinition.addContents(
title: "Upload",
id: "upload",
label: "Upload",
elements: [
type: "html",
html: '<form><input id="imageupload" type="file" name="files[]" />%csrf_token%</form>'
]
);
);
这是对我的真实世界版本的未经测试的简化,但希望它显示了这个想法。
这不会在图像对话框中设置 URL 字段,因此单击对话框上的“确定”会显示错误消息。您需要在成功上传时进行设置,因此:
CKEDITOR.dialog.getCurrent().getContentElement('info', 'txtUrl').setValue(theURL);
【讨论】:
哇,对旧问题的新回答 :-) 谢谢!!...你的方法比我破解 ckeditor 代码要干净得多。下次我必须使用ckeditor时,我会尝试你的方式。 我得到:“未捕获的类型错误:无法读取 null 的属性 'getContentElement'”我错过了什么?【参考方案2】:发送到服务器的额外数据通过get请求传递。我试图添加额外的数据,并最终实现了添加到用于发送数据的表单的 url 参数
CKEDITOR.on('dialogDefinition', function(ev)
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if (dialogName == 'image')
dialogDefinition.contents[2].elements[0].action += '&pin=123456';
/* 2 is the upload tab it have two elements 0=apparently is the
and 1: is the button to perform the upload, in 0 have the action property with the parameters of the get request simply adding the new data
*/
);
【讨论】:
【参考方案3】:我在通过 CKEditor for Elgg 集成图像上传时遇到了类似的问题。我想出的侵入性最小的解决方案是绑定到提交按钮的 onClick 事件并直接从中修改表单:
CKEDITOR.on('dialogDefinition', function (ev)
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
if (dialogName === 'image')
var uploadTab = dialogDefinition.getContents('Upload');
for (var i = 0; i < uploadTab.elements.length; i++)
var el = uploadTab.elements[i];
if (el.type !== 'fileButton')
continue;
// add onClick for submit button to add inputs or rewrite the URL
var onClick = el.onclick;
el.onClick = function(evt)
var dialog = this.getDialog();
var fb = dialog.getContentElement(this['for'][0], this['for'][1]);
var action = fb.getAction();
var editor = dialog.getParentEditor();
editor._.filebrowserSe = this;
// if using jQuery
$(fb.getInputElement().getParent().$).append('<input type="hidden" name="foo" value="bar">');
// modifying the URL
fb.getInputElement().getParent().$.action = '/my/new/action?with&query¶ms=1';
if (onClick && onClick.call(evt.sender, evt) === false)
return false;
return true;
;
);
【讨论】:
【参考方案4】:不编辑ckeditor源码好像没有办法给ckeditor上传数据添加数据。要修改的源代码是 plugins/dialogui/plugin.js,在 ckeditor 3.6.2 的第 1440 行附近,其中 ckeditor 创建了上传 iframe 使用的表单。
// ADDED TO CKEDITOR CODE %<
var csrfitems = document.getElementsByName("csrfmiddlewaretoken")
var csrftoken = ""
if(csrfitems.length > 0)
csrftoken = csrfitems[0].value
// >% END OF ADDED CODE
if ( elementDefinition.size )
size = elementDefinition.size - ( CKEDITOR.env.ie ? 7 : 0 ); // "Browse" button is bigger in IE.
frameDocument.$.write( [ '<html dir="' + langDir + '" lang="' + langCode + '"><head><title></title></head><body style="margin: 0; overflow: hidden; background: transparent;">',
'<form enctype="multipart/form-data" method="POST" dir="' + langDir + '" lang="' + langCode + '" action="',
CKEDITOR.tools.htmlEncode( elementDefinition.action ),
'">',
// ADDED TO CKEDITOR CODE
'<input type="hidden" name="csrfmiddlewaretoken" value="',csrftoken,'"/>',
// >% END OF ADDED CODE
'<input type="file" name="',
CKEDITOR.tools.htmlEncode( elementDefinition.id || 'cke_upload' ),
'" size="',
CKEDITOR.tools.htmlEncode( size > 0 ? size : "" ),
'" />',
'</form>',
现在我们可以在 ckeditor 中使用 django 安全上传
【讨论】:
【参考方案5】:这个问题太老了,但是……
4.5 版您可以将钩子添加到任何请求中
editor.on( 'fileUploadRequest', function( evt )
var xhr = evt.data.fileLoader.xhr;
xhr.setRequestHeader( 'Cache-Control', 'no-cache' );
xhr.setRequestHeader( 'csrf header ', 'HEADER' );
xhr.withCredentials = true;
);
【讨论】:
不适用于默认的 FileBrowser 上传:***.com/questions/34851158/…【参考方案6】:如果您通过 HTTPS 在 URL 中发送 CSFR 令牌,这样做应该没问题(从安全角度来看),而且处理起来也容易得多。
假设 django 可以读取该变量,或者您可以轻松地修改 django。这些试图改变 CKeditor 的答案在 imo 看来工作量太大了。
只要用户浏览器以安全的方式将您的 CSFR_token 发送到服务器,无论是通过 POST 还是 GET 都没有关系。安全问题是中间人攻击,即您不希望用户 CSFR_token 以纯文本形式广播。
严格来说,这种数据应该根据 HTTP 规范作为 POST 发送,但这似乎是一种“滥用”GET 协议可能是可以接受的情况,因为您无法以特别优雅的方式控制 CKEditor 代码方式。
此外,如果 CKEditor 在升级过程中发生更改,您可能会被抓住,通过 URL 传递令牌将始终有效。
【讨论】:
以上是关于如何在 CKeditor 上传中向 POST 值添加字段的主要内容,如果未能解决你的问题,请参考以下文章
使用 CKEditor CDN 时如何从桌面上传 CKEditor 中的图像?
angular+ckeditor最后上传的最后一张图片不会被添加(bug)
如何使用 ReactJS 在 CKEditor 5 中配置上传适配器?