我需要一个安全的解决方案来存储仅由特定用户访问的更大(未知)数量的私有图像。这个问题不包括登录,会话或其他类似的事情 - 仅围绕图像并存储它们。
我开始解释我想要实现的目标,然后继续我想到的事情。
私人图片只能由特定用户访问
用户登录我的网站上传和查看他/她提供和上传的图片。图像只能由该用户访问 - 因此需要登录。请求查看图像时,渲染由PHP脚本处理,验证用户的权限并从安全目录中提取实际图像。
我所知道的,假设和思考。
为便于管理而对图像编制索引
上传的每张图片都会在数据库中编入索引进行管理,即
Title: "Me on a scooter"
User: {0E4A759A-CC31-4B0D-97E1-EEFB28F0BF86}
Filename: asuohLAFUUHJSFUhaSGFUOAHSGUA
Extension: .jpg
当用户想要查看图像时,服务器会验证并检查用户是否确实是图像的所有者。
让公众远离图像
我已经阅读了一些文章,解释了将文件保留在文档根目录之外的良好做法。虽然我理解这个概念,但我并不完全明白如何在实践中做到这一点。我的假设:
/var/www/myFolder/ //here's where the html files are stored
/mySecureFolder/ //here's where the content are stored outside of the root, or on a higher level
因此,只要服务器显示图像,它就会在/ mySecureFolder /中查找它,并在为用户呈现文件之前检查该文件是否存在。
假设#2
创建并放置一个.htaccess文件,阻止除了/ mySecureFolder /中的localhost之外的所有人,我应该做些什么来阻止其他人。
问题#1 PHP进程作为用户www-data运行,是否可以安全地建立/ mySecureFolder / www-data的所有者组?
假设#3 - Chmod
要允许除一个特定系统用户以外的任何用户,我应该使用0770 recursiv CHMOD该文件夹,只允许所有者用户和所有者组读取,写入和执行权限。
问题#2
使用.htaccess拒绝访问除了localhost之外的所有人,但相当于将安全文件夹放在root(/ var / www / myFolder /)文件夹之外?
假设#4 Overkill
加密存储在文件系统上的每个图像都是过度的,如果目录权限设置正确则不必要。
我的攻击场景只是外部攻击,黑客无法通过SSH访问服务器,也无法通过物理访问服务器。因此,可能的攻击是来自我创建的代码的外部攻击 - 如注射等。
我希望未来的旁观者可能会得到可能的答案,因此如果您帮我格式化这个问题以确保其尽可能清晰,我将不胜感激。
答案 0 :(得分:3)
最好的方法是将图像存储在/ www之外 - 并将它们放在自己的目录中。
然后使用readfile()
来提供服务'图像给授权用户。无需CHMOD或使用htaccess等 - 因为它位于www文件夹之外,除非通过您的应用程序,否则无法访问。
这样的事情会起作用:
function show_image($file_name= "")
{
// Ensure no funny business names to prevent directory transversal etc.
$file_name = str_replace ('..', '', $file_name);
$file_name = str_replace ('/', '', $file_name);
// now do the logic to check user is logged in - put your own code here
if (LoggedInUserCanAccessThisFile())
{
// Serve file via readfile()
// Images are stored in a specific user folder - so only the own user can get their own images
readfile('../image_storage/' . getLoggedInUserID() . '/' . $file_name);
}
}
您可以阅读有关readfile() here from php.net
的更多信息答案 1 :(得分:1)
我正在研究类似的问题;但是,我可能会改变我的逻辑以合并readfile()函数。但是现在,我将图像放在公共html文件夹之外的安全文件夹中。 php脚本将目录读取到会话数组,然后按文件名对其进行排序。第二个脚本使用html来导航文件名数组。选择文件后,会将其复制到tmp公共图像目录并通过html显示。在选择下一个文件之前,将从tmp目录中删除前一个文件。原始文件保留在安全文件夹中。这可能有点尴尬,但对我来说效果很好。