繁体   English   中英

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

[英]PHP security and unique naming conventions

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

/user_id-username.jpg

例子:

/1-feont.jpg

所有图像都有唯一的名称(因为 user_id 是主键),但是安全性呢? 这有什么不好的影响吗? 如果有,我应该做哪些约定?

在将用户名用作文件名的一部分之前,请确保对其进行了适当的清理。 用户 ID 应该是系统生成的,这样不会导致任何问题。

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

但这个想法真的很牵强。 您可以使用用户名提前 go。 :-)

IMO,只需将图像命名为user-user_id.jpg (这里,“user”是一个普通字符串,后跟 integer - user_id)

一般来说,这很好,但有些用户可能不喜欢显示他们的姓名,并且如果您的站点不完全安全,或者如果将来发现 PHP 漏洞目前未知,则作为主键的用户 ID 可能存在漏洞。

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

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

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

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

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

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

*编辑 - *另一种选择是使用现有格式并创建一个 MD5 hash,代码类似于

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

我希望这有帮助

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

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

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

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

总而言之,我将 go 与 ID。

像您在第一个示例中使用的方式命名文件没有巨大风险,但为了使其更安全,为什么不使用更好的东西,例如

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

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

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

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

如果算法很难写,可以试试这个function:

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;
}

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

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

图像表

编号 | 用户 ID | 文件名 | ETC

只有我自己的两分钱。 如果您要添加更多头像供用户选择,最好使用像 uniqid() 这样的 function 而不是 user of。 否则,您可以随心所欲。

不过,我使用用户 ID 和 time() 的 MD5 hash。 只是偏好问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM