如何为用户上传的图像提供服务?

时间:2012-05-31 18:04:08

标签: php file-upload

我正在构建一个小型网络应用,允许登录用户上传产品图片。我正在尝试构建它,并且在过去的一些天真实现之后,决定在我的公共文件夹中添加所有上传的内容。

\app (public folder)
-\index.php
\includes
\config
\uploads

如果恶意用户设法上传PHP文件,服务器将无法访问或提供服务,这将使其成为现实。

话虽如此,我将如何在网页上提供这些图片?做这个的最好方式是什么?在过去,我使用了一个getImage.php文件,该文件将采用ID参数(以及一些生成值的哈希以避免用户只是猜测ID),这些文件看起来像“getImage.php?id = 555& c = 44j54k3h5” 。服务器抓取DB(真实路径)中的图像信息并加载内容,重建标题并发送图像。

此方法是否存在任何安全问题?有没有办法让它更漂亮?有一个htaccess重写规则,寻找/images/imagename.jpg并将它们发送到我的getImage.php文件添加安全漏洞?任何关于最佳实践的建议都将不胜感激。

3 个答案:

答案 0 :(得分:3)

查看此课程。它将处理上传,进行安全检查并让你喝咖啡:)

http://www.verot.net/php_class_upload.htm

答案 1 :(得分:1)

为上传图片提供服务的方法的安全性确实取决于很多其他因素。

  • 上传时如何处理和保护图片/文件?什么是 上传的目录/文件权限?
  • 哪些进程可以读取和写入这些位置?
  • 您有哪些类型的文件处理程序可以执行任意文件?
  • 如果您要使用PHP-> get_image-> display_image路线,是否会尝试在上传后防止恶意意图(在getimage上?)

我会使用Apache mod_alias来引用webroot上面的目录。这样,您仍然可以使用链接到图像而无需打开完整的根目录进行曝光。

答案 2 :(得分:1)

“更漂亮”的方法是使用.htaccess重定向

RewriteEngine On                                                                                                                                                                                                                                  
RewriteBase /                                                                                                                      
RewriteRule ^getImage/([0-9]+)/(.+)\.png$ getImage.php?id=$1&c=$2 [NC,L]

然后在getImage.php

if (isset($_GET['id']) && isset($_GET['c'])) {

    // set headers
    header("Content-Type: image/png");

    // cache control
    header("Cache-Control: private, max-age=10800, pre-check=10800");
    header("Pragma: private");
    header("Expires: " . date(DATE_RFC822, strtotime("2 day")));
    if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
            header('Last-Modified: ' . $_SERVER['HTTP_IF_MODIFIED_SINCE'], true, 304);                                    
            exit;                            
    }

    /* do things */
    imagepng($image_resource);
    imagedestroy($image_resource);
}
else {

    echo "bad request";
}

所以而不是

site.com/getImage.php?id=555&c=44j54k3h5

你会用

site.com/getImage/555/44j54k3h5.png

此方法没有任何额外的安全风险或循环漏洞。只需确保在查询之前转义get变量以避免注入攻击。

如果您想保护自己免受恶意文件上传的影响,则需要在投放之前执行此操作。