将上载的图像放在公用文件夹中是否安全?
我刚刚与我的队友讨论了用户上传的图像在图像库中的位置。我希望对我们建议的方法有更广泛的了解。
我的队友编写了一个控制器 + 操作,该操作调用放置在不可用于公共浏览的文件夹中(即,在服务器上的外部)中的图像文件,并通过标头进行回显。这是安全的,但是由于我们使用Zend框架,它也爬行速度很慢 - 由于执行引导的查询,每次调用图像控制器都会花费我们大约500ms的延迟。这很烦人,因为图片库视图同时显示20多张图像。file_get_contents
public_html
简而言之,相关代码将是:
class ImageController extends Zend_Controller_Action {
public function showAction () {
$filename = addslashes($this->_getParam('filename'));
if(!is_file($filename)) {
$filename = APPLICATION_PATH.'/../public/img/nopicture.jpg';
}
$this->_helper->viewRenderer->setNoRender(true);
$this->view->layout()->disableLayout();
$img = file_get_contents($filename);
header('Content-Type: image/jpeg');
$modified = new Zend_Date(filemtime($filename));
$this->getResponse()
->setHeader('Last-Modified',$modified->toString(Zend_Date::RFC_1123))
->setHeader('Content-Type', 'image/jpeg')
->setHeader('Expires', '', true)
->setHeader('Cache-Control', 'public', true)
->setHeader('Cache-Control', 'max-age=3800')
->setHeader('Pragma', '', true);
echo $img;
}
}
然后,在视图中,我们只需调用:
<img src="<?php echo $this->url(array('controller' => 'image', 'action' => 'show', 'filename' => PATH_TO_HIDDEN_LOCATION.'/filename.jpg')); ?>" />
我有一种不同的方法:我更喜欢将原始图像保存在隐藏位置,但是一旦请求,请立即将它们复制到公共位置并提供指向它的链接(使用由cron运行的额外机制,不时擦除公共图像目录,以免浪费空间, 并告诉谷歌不要索引该目录)。该解决方案将文件(每个给定时刻的几个)放在可公开访问的目录中(前提是知道文件名),但也只需要一个视图帮助程序,因此不会启动引导程序:robots.txt
class Zend_View_Helper_ShowImage extends Zend_View_Helper_Abstract {
public function showImage ($filename) {
if (!file_exists(PUBLIC_PATH."/img/{$filename}")) {
if (!copy(PATH_TO_HIDDEN_FILES."/{$filename}",PUBLIC_PATH."/img/{$filename}"))
$url = PUBLIC_PATH.'/img/nopicture.jpg';
else
$url = PUBLIC_PATH."/img/{$filename}";
} else {
$url = PUBLIC_PATH."/img/{$filename}"
}
return "{$url}";
}
}
借助此助手,调用在视图中非常简单:
<img src="<?php echo $this->showImage('filename.jpg'); ?>" />
问题:我的方法是否像我的同事所说的那样构成安全威胁?这有哪些潜在的风险?而且,最重要的是,安全威胁(如果有的话)是否超过了页面加载的10秒?
如果这很重要:我们正在开发一个拥有大约15K注册用户的社区门户,其中画廊是一个非常常用的功能。
*我粘贴的代码是我们每个人想出的经过编辑的简化版本 - 只是为了展示这两种方法的机制。