PHP安全性和独特的命名约定

时间:2011-07-04 18:49:02

标签: php security naming-conventions

命名由用户(例如头像)上传的图像有什么问题:

/user_id-username.jpg

示例:

/1-feont.jpg

所有图片都有唯一的名称(因为user = id是主键),但安全性如何呢?那有什么不好的影响吗?如果有,我应该做些什么约定?

8 个答案:

答案 0 :(得分:1)

在将用户名作为文件名的一部分使用之前,请确保已正确清理用户名。用户ID应该是系统生成的,这样不会引起任何问题。

答案 1 :(得分:1)

您提供图像的名称纯粹是传统的。我不认为泄露用户的用户名是一个安全问题。 (如果是,那么您最好立即检查您的CMS!)但是,如果您的网站不完全安全,黑客可以使用SQL注入来访问您的用户数据。

但这个想法实在是太牵强了。您可以继续使用用户名。 : - )

IMO,只需将图像命名为user-user_id.jpg(此处,“user”为普通字符串,后跟整数 - user_id)

答案 2 :(得分:1)

通常它很好,但有些用户可能不喜欢显示他们的名字,如果您的网站不是完全安全或者将来发现的PHP漏洞,那么作为主键的用户ID可能会有漏洞未知。

对于这类事情,我倾向于使用以下代码

$createName = date('YmdHis');
$fileType = '.jpg';
$imgName = $createName.$fileType;

这应该给出一个像20110702155513.jpg这样的字符串 - 这是图像命名的完整日期和时间,并且是唯一的。

如果您真的想要安全,那么您可以编写一个回调函数,如果由于文件名不唯一而导致失败(通常是因为在同一秒内有2个请求 - 不太可能但可能),那么您可以使用回退在字符串中间添加用户ID或使用回退作为主要命名方法,例如

if($imgName == 'inuse'){
     $createName1 = date('Ym');
     $createName2 = date('dHis');
     $fileType = '.jpg';
     $imgName = $createName1.$userId.$createName2.$fileType;
}

这允许隐藏用户ID,但完全唯一。

* 编辑 - * 另一种选择是使用现有格式并创建一个MD5哈希,代码就像

$user_id = 'user_id';
$username = 'username';
$fileType = '.jpg';
$fileName = md5($user_id).'-'.md5($username).$fileType;

我希望这会有所帮助

答案 3 :(得分:1)

  • 使用日期,因为Ryan建议您在同时上传用户时失败
  • 当用户更改用户名时,使用用户名会失败。 “失败”在这里有点困难,但你必须移动文件,这是使用其他解决方案时不需要的东西
  • 如果ID是数据库中自动生成的自动增量ID,则使用 id 可以解决所有并发问题。与 Kerrek SB 相反,我没有发现这会在唯一标识符和文件系统上的图像之间建立连接的问题。我的意思是它是独一无二的,你可以使用它。

如果您经常公开使用ID,使用该ID还可以让您的用户轻松查找/链接他们的图片。另一方面,如果你只有URL中的用户名 - 比如/profile/$username,那么我也会在图像文件名中使用用户名 - 以保持一致。

关于安全性:如果您清理用户名,一切都很好。只要确保它是唯一的,这样人们就不能覆盖彼此的名字(这意味着你需要对数据库中的用户名使用与用于图像文件名中的用户名相同的卫生规则)。

将用户名作为图像名称,如果您手动需要找到图像,也可以“更容易”找到图像,但这可能不会经常发生,对您来说是值得的。

总结一下,我会使用ID。

答案 4 :(得分:0)

命名文件没有很大的风险,就像你在第一个例子中使用的那样,但为了让它更安全,为什么不使用更好的东西,比如

    function Naming($username,$imagename)
{
    $uniq = time() ;
    $name  = $uniq.'-'.$username.'-'.$imagename ;
    return $name ;
}

我认为最好避免使用用户ID

答案 5 :(得分:0)

唯一的user_id就足够了,你不需要“用户名” 问题不在这里,而是文件数量(在一个文件夹中) 在文件夹(或100)中将它们拆分为1000:取ID字符串的第一,第二和第三个符号并放入单独的目录:

ID = 10524.jpg  
filename = 1/0/5/10524.jpg

如果编写算法很困难,可以试试这个功能:

function getStorePath($filename, $base_dir)
{
    //file should have extension
    $ext_pos = strrpos($filename, '.');
    if ($ext_pos===false) return false;

    //extension will be sanitized (filtered actually)    
    $ext = preg_replace("|\W+|", "", substr($filename, $ext_pos+1));
    if (empty($ext)) return false;
    if (in_array($ext, array('php', 'shtml', 'cgi', 'inc', 'module', 'sh', 'sql', 'class'))) return false;

    //filename will be filtered    
    $filename = preg_replace("|\W+|", "", substr($filename, 0, $ext_pos));

    if (empty($filename)) $filename = mt_rand(100000, 999999).round(microtime(true)*1000000);

    //let's create path to the file.
    //we will take first 3 symbols of filename as names of folders    
    $d = realpath($base_dir).'/';

    //first symbol
    $d .= $filename[0].'/';
    if (!file_exists($d))
    {
        $md = mkdir($d, 0755);
        if ($md===false && !file_exists($d)) return false;
    }

    //second symbol
    if (isset($filename[1]))
    {
        $d .= $filename[1].'/';
        if (!file_exists($d))
        {
            $md = mkdir($d, 0755);
            if ($md===false && !file_exists($d)) return false;
        }
    }

    //and third symbol
    if (isset($filename[2]))
    {
        $d .= $filename[2].'/';
        if (!file_exists($d))
        {
            $md = mkdir($d, 0755);
            if ($md===false && !file_exists($d)) return false;
        }
    }

    if (!file_exists($d.$filename.'.'.$ext)) return $d.$filename.'.'.$ext;
    else return false;
}

答案 6 :(得分:0)

我通常将我的图像命名为随机字符串,然后将其存储在附加到上传者ID的数据库中。您还可以通过这种方式存储有关图像的其他数据。

$ filename = uniqid('',true)。名为.jpg;

图像表

id | user_id |文件名|等

答案 7 :(得分:0)

只是我自己的两分钱。 如果你要为用户添加更多的头像供你选择,你最好使用uniqid()等功能而不是用户。否则,你可以随心所欲地做到这一点。

我使用了userid和time()的MD5哈希值。只是一个偏好问题。