使用WordPress安全问题预览和发布前端图像

时间:2013-04-07 07:31:53

标签: php wordpress security upload

我有一个带有文件输入的前端表单,其中 anybody (没有注册用户)可以上传将附加到后端自定义元字段的图像。要预览图像,我正在使用旧的iframe技术。我的表格如下:

<form id="upload-photo" method="post" target="preview-iframe" action="<?= get_template_directory_uri() ?>/inc/upload.php" enctype="multipart/form-data" >
  <div id="preview"><img src="" alt="" /></div>
  <iframe id="preview-iframe" name="preview-iframe" src=""></iframe>
  <input type="file" name="author_photo" />
  <input type="hidden" id="attachment" name="attachment" value=""/>
  <button type="submit" id="upload">Upload</button>
</form>

然后我使用WordPress内置函数来处理上传并将文件移动到媒体库中。我使用隐藏字段存储附件的WordPress id,因此如果用户决定通过上传新图片来更改图片,那么旧图片将被删除。这是我的PHP:

<?php
define('WP_USE_THEMES', false);
require_once '../../../../wp-load.php';
require_once(ABSPATH .'wp-admin/includes/image.php');
require_once(ABSPATH .'wp-admin/includes/file.php');
require_once(ABSPATH .'wp-admin/includes/media.php');

if (isset($_POST['attachment'])) {
  wp_delete_attachment($_POST['attachment'], true);
}

foreach ($_FILES as $file => $data) {
  if ($data['error'] === UPLOAD_ERR_OK) {
    $attachment = media_handle_upload($file, null);
  }
}

echo wp_get_attachment_image($attachment, 'author', 0, array('id' => $attachment));
?>

最后jQuery将它们粘在一起:

var $preview = $('#preview'),
    $iframe = $('#preview-iframe'),
    $attachment = $('#attachment');

$('#upload').click(function() {
  $iframe.load(function() {
    var img = $iframe.contents().find('img')[0];
    $preview.find('img').attr('src', img.src);
    $attachment.val(img.id);
  });
});

一切都很完美,但这种简单的方法几乎没有问题:

  • 如果禁用JavaScript,则图片不会被删除

  • 如果用户上传文件然后刷新网站,然后上传和其他图片,则之前的附件不会被删除,因为之前的附件ID因刷新而不存在。

  • 恶意用户可以使用其他ID编辑隐藏的attachment字段。

我想将文件上传到/temp文件夹仅用于预览,然后每隔X次运行一次cron作业以清空它。但是,如果整个表单已经提交,我如何利用WordPress函数将图像从/temp移动到图库,这样我就可以获得附件ID以链接到帖子?

请注意,我有两个表单,一个用于处理图像,另一个表单包含将要发布的所有内容,并且已经有效,因为我可以将新帖子发布为“草稿”,管理员有权使用决定。但如何安全地为图像做这个?如果表单已成功发布,如何预览图片并将其放入图库

我知道FileReader API,但我需要IE8 +的兼容性,所以不会这样做。我也知道所有的Flash和Silverlight解决方案,但这也不是一个选择。另外,请不要只链接到WordPress插件,我想在这里学习。

1 个答案:

答案 0 :(得分:0)

好吧,我似乎又回答了自己的问题。这就是我解决它的方式。我找到了一个WordPress函数media_handle_sideload,它允许您从其他位置上传文件,而不仅仅像上一个函数一样从$_FILES数组中上传文件。

所以我现在采用了我最初的方法,因为我知道这个功能。我基本上将文件上传到/temp文件夹以进行预览,并为其提供一个唯一的ID,我将其存储到隐藏字段中。当用户提交整个表单并通过验证时,我会获取存储的ID并查明文件是否存在,如果是,我将其移动到库中。这解决了我对安全性的大多数担忧,因为即使恶意用户发现现有的唯一ID(不太可能但可能),该文件也不会像之前那样被删除,而只是移入图库(不是很大)。

最后,我设置了一个cron作业,每隔X个时间清空临时文件夹。