简体   繁体   English

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

[英]PHP security and unique naming conventions

Is anything wrong with naming images uploaded by users (for example avatars) like that:像这样命名用户上传的图像(例如头像)有什么问题:

/user_id-username.jpg

Example:例子:

/1-feont.jpg

All images has unique name (becouse user_id is primary key), but what about security?所有图像都有唯一的名称(因为 user_id 是主键),但是安全性呢? Has that any bad influence?这有什么不好的影响吗? If has, what conventions should I do instead?如果有,我应该做哪些约定?

Make sure that the username is appropriately sanitized before using it as part of the filename.在将用户名用作文件名的一部分之前,请确保对其进行了适当的清理。 User id should be system generated so that should not cause any problems.用户 ID 应该是系统生成的,这样不会导致任何问题。

The name that you give the images is purely conventional.你给图像起的名字纯粹是传统的。 I do not think it is a security issue for revealing the usernames of your users.我不认为泄露用户名是一个安全问题。 (If it is, then you better check your CMS right away,) However. (如果是,那么您最好立即检查您的 CMS,)但是。 if your website is not completely secure a hacker can make use of SQL injection to access your user data.如果您的网站不完全安全,黑客可以利用 SQL 注入来访问您的用户数据。

But the idea is really far-fetched.但这个想法真的很牵强。 You can go ahead with using usernames.您可以使用用户名提前 go。 :-) :-)

IMO, just name the images as user-user_id.jpg (Here, "user" being a normal string followed by the integer - user_id) IMO,只需将图像命名为user-user_id.jpg (这里,“user”是一个普通字符串,后跟 integer - user_id)

Generally it is fine but some users may not like their name to be displayed and the user ID being a primary key could have vulnerability if your site isn't completely secure or if a PHP vulnerability is found in the future that is currently unknown.一般来说,这很好,但有些用户可能不喜欢显示他们的姓名,并且如果您的站点不完全安全,或者如果将来发现 PHP 漏洞目前未知,则作为主键的用户 ID 可能存在漏洞。

For this sort of thing I tend to use the following code对于这类事情,我倾向于使用以下代码

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

This should give a string like 20110702155513.jpg - this is the full date and time the image was named and is unique.这应该给出一个类似 20110702155513.jpg 的字符串 - 这是图像命名的完整日期和时间,并且是唯一的。

If you really want to be safe then you can write a call back function that if there was a failure due to the file name not being unique (generally because there were 2 requests in the same second - unlikely but possible), then you can use a fall back adding the user ID in the middle of the string or use the fall back as your primary naming method, so for example如果你真的想要安全,那么你可以写一个回调 function 如果由于文件名不唯一而失败(通常是因为在同一秒内有 2 个请求 - 不太可能但可能),那么你可以使用回退在字符串中间添加用户 ID 或使用回退作为您的主要命名方法,例如

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

This allows the user ID to be hidden but entirely unique.这允许用户 ID 被隐藏但完全唯一。

* Edit - * another option is to use the existing format and create an MD5 hash, the code would be something like *编辑 - *另一种选择是使用现有格式并创建一个 MD5 hash,代码类似于

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

I hope this helps我希望这有帮助

  • Using the date as Ryan suggests fails when you have users that upload at the same time当您有同时上传的用户时,使用 Ryan 建议的日期会失败
  • Using the username fails when users may change their username.当用户可以更改其用户名时,使用该用户名会失败。 "Fail" is a bit hard here, but you have to move the files around which is something that's not needed when using another solution “失败”在这里有点困难,但是您必须移动文件,这是使用其他解决方案时不需要的东西
  • Using the id solves all concurrency problems if the ID is an autogenerated auto-increment ID from your database.如果 ID 是数据库中自动生成的自动增量 ID,则使用id可以解决所有并发问题。 Opposed to Kerrek SB , I don't see a problem that this makes a connection between a unique identifier and an image on your file system.Kerrek SB相反,我认为这不会在唯一标识符和文件系统上的图像之间建立联系。 I mean it's unique and you can use it.我的意思是它是独一无二的,你可以使用它。

Using the ID also makes it easy for your users to find/link their image if you constantly use the ID publicly.如果您经常公开使用 ID,使用 ID 还可以让您的用户轻松找到/链接他们的图像。 If you on the other hand have only the user names in URLs - like /profile/$username , then I'd use the username in the image file name, too - to be consistent.另一方面,如果您在 URL 中只有用户名 - 例如/profile/$username ,那么我也会在图像文件名中使用用户名 - 保持一致。

About security: If you sanitize the username, all is fine.关于安全性:如果您清理用户名,一切都很好。 Just make sure that it's unique, so people can't overwrite each other's names (which means that you need to use the same sanitation rules for usernames in database as you use for usernames in image file names).只要确保它是唯一的,这样人们就不能覆盖彼此的名字(这意味着您需要对数据库中的用户名使用与图像文件名中的用户名相同的卫生规则)。

Having the username as image name also makes it "easier" to find an image if you manually need to find one, but that probably happens not often enough to be of worth for you.如果您需要手动查找图像,使用用户名作为图像名称也可以“更容易”找到图像,但这可能并不经常发生,对您来说不值得。

To summarize, I'd go with the ID.总而言之,我将 go 与 ID。

there is no huge risk to naming files like the way you use in your first example but to make it more secure why don't you use something better like像您在第一个示例中使用的方式命名文件没有巨大风险,但为了使其更安全,为什么不使用更好的东西,例如

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

i think its better to avoid using users ID's我认为最好避免使用用户 ID

Unique user_id is enough, you don't need "username".唯一的 user_id 就足够了,你不需要“用户名”。
Problem isn't here, but in count of files (in one folder).问题不在这里,而在于文件数(在一个文件夹中)。
Split them by 1000 in folder (or by 100): take first, second and third symbols of ID string and put in separate dirs:在文件夹中将它们除以 1000(或除以 100):获取 ID 字符串的第一个、第二个和第三个符号并放入单独的目录中:

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

If it's hard to write algorithm, you can try this function:如果算法很难写,可以试试这个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;
}

I typically name my images a random string, then store it in the database attached to the uploaders id.我通常将我的图像命名为随机字符串,然后将其存储在附加到上传者 ID 的数据库中。 You can also store other data about the image this way.您还可以通过这种方式存储有关图像的其他数据。

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

Image Table图像表

id |编号 | user_id |用户 ID | filename |文件名 | etc ETC

Just my own two cents.只有我自己的两分钱。 If you are gonna add more avatars for users to choose from, you're better off using a function like uniqid() instead of the user of.如果您要添加更多头像供用户选择,最好使用像 uniqid() 这样的 function 而不是 user of。 Else, you can do that all you like.否则,您可以随心所欲。

I use an MD5 hash of the userid and time() though.不过,我使用用户 ID 和 time() 的 MD5 hash。 Just a matter of preference.只是偏好问题。

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

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