【发布时间】:2012-05-08 05:16:04
【问题描述】:
我有一个 URL,它将向我的用户提供受保护的文件。
文件名在上传文件时由我的应用程序重写,无论名称如何,并存储在我的数据库中。所以我知道它永远不会包含“/”或“..”
文件名是:"USER_ID"_"RANDOMMD5".FILE_EXT 使用“USER_ID”=当前登录的用户 ID 和“RANDOM MD5”。
即5_ji3uc237uckj92d0jf3932t09ut93f2.pdf
这是我提供文件的功能:
function user_file($file_name = "")
{
if ($file_name)
{
// Ensure no funny business names:
$file_name = str_replace ('..', '', $file_name);
$file_name = str_replace ('/', '', $file_name);
// Check if the user is allowed to access this file
$user_id = substr($file_name, 0, strpos($file_name, "_"));
// now do the logic to check user is logged in, and user is owner of file
(($this->ion_auth->logged_in()) && (($user_id === $this->user->id))
{
// Serve file via readfile()
}
}
}
问题:这是一种安全的方式来确保该人没有其他方式可以横穿目录、访问其他文件等吗?
edit 1: ion_auth 是我的身份验证库,“$this->user->id”是存储在我的构造中的用户 ID
编辑 2: 用户文件存储在 public_html 之外 - 因此只能通过我的应用程序 AFAIK 访问
编辑 3: 我改进的代码,使用下面 Amber 的想法,考虑到我需要适应不同的文件扩展名,我将尝试避免数据库命中:
function user_files($file_name = "")
{
// for security reasons, check the filename is correct
// This checks for a 32bit md5 value, followed by a single "." followed by a 3-4 extension (of only a-z)
if (preg_match('^[A-Za-z0-9]{32}+[.]{1}[A-Za-z]{3,4}$^', $file_name))
{
// Now check the user is logged in
if ($this->ion_auth->logged_in())
{
// Rewrite the request to the path on my server - and append the user_id onto the filename
// This ensures that users can only ever access their own file which they uploaded
// As their userid was appended to the filename during the upload!
$file = MY_SECURE_FOLDER.$this->user->id.'_'.$file_name;
// Now check if file exists
if (file_exists($file))
{
// Serve the file
header('Content-Type: '.get_mime_by_extension($file));
readfile($file);
}
}
}
}
【问题讨论】:
-
文件是否仍在网络可访问的目录中?如果是这样,您的问题的答案是否。
-
嗨 rdlowrey - 谢谢 - 我应该提到该文件存储在 Public_html 之外 - 因此只能通过应用程序访问 - 感谢您考虑到这一点 - 我将编辑我的问题
-
看起来不错。对于这样的系统,我唯一会担心的是,您可能会在一个目录中拥有大量文件。在具有 ext3 或 windows fat32 文件目录的 linux 服务器上,如果例程涉及使用 readdir() libc 调用,您可能会遇到性能问题。
标签: php security file codeigniter