Безопасность PHP и уникальные соглашения об именах - PullRequest
1 голос
/ 04 июля 2011

Что-то не так с именами изображений, загружаемых пользователями (например, аватарами), например:

/user_id-username.jpg

Пример:

/1-feont.jpg

Все изображения имеют уникальное имя (потому что user_id является первичнымключ), а как насчет безопасности?Имеет ли это какое-либо плохое влияние?Если есть, какие соглашения я должен вместо этого сделать?

Ответы [ 8 ]

1 голос
/ 05 июля 2011
  • Использование даты , как полагает Райан, не удается, если у вас есть пользователи, которые загружают одновременно
  • Использование имени пользователя не удается, когда пользователи могут изменить свое имя пользователя. «Fail» здесь немного сложнее, но вы должны перемещать файлы, что не нужно при использовании другого решения
  • Использование id решает все проблемы параллелизма, если идентификатор является автоматически сгенерированным идентификатором автоинкремента из вашей базы данных. В отличие от Kerrek SB , я не вижу проблемы в том, что это создает связь между уникальным идентификатором и изображением в вашей файловой системе. Я имею в виду, что он уникален, и вы можете использовать его.

Использование идентификатора также позволяет вашим пользователям легко находить / связывать свое изображение, если вы постоянно используете идентификатор публично. Если, с другой стороны, в URL-адресах есть только имена пользователей - например, /profile/$username, то я бы использовал имя пользователя и в имени файла изображения - для согласованности.

О безопасности: если вы очистите имя пользователя, все в порядке. Просто убедитесь, что он уникален, чтобы люди не могли перезаписывать имена друг друга (это означает, что вам нужно использовать те же правила санитарии для имен пользователей в базе данных, что и для имен пользователей в именах файлов изображений).

Наличие имени пользователя в качестве имени изображения также облегчает поиск изображения, если вам нужно вручную его найти, но это, вероятно, происходит не достаточно часто, чтобы быть полезным для вас.

Подводя итог, я бы пошел с удостоверением личности.

1 голос
/ 04 июля 2011

Обычно это нормально, но некоторым пользователям может не нравиться, когда их имя отображается, а идентификатор пользователя, являющийся первичным ключом, может иметь уязвимость, если ваш сайт не полностью защищен или если в будущем будет обнаружена уязвимость PHP. неизвестно.

Для такого рода вещей я обычно использую следующий код

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

Это должно дать строку типа 20110702155513.jpg - это полная дата и время, когда изображение было названо и является уникальным.

Если вы действительно хотите быть в безопасности, вы можете написать функцию обратного вызова, которая, если произошел сбой из-за того, что имя файла не было уникальным (обычно потому, что в одну секунду было 2 запроса - маловероятно, но возможно), тогда вы можете использовать резервное добавление идентификатора пользователя в середине строки или использовать откат в качестве основного метода именования, например,

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

Это позволяет скрыть идентификатор пользователя, но полностью уникален.

* Редактировать - * другой вариант - использовать существующий формат и создать хеш MD5, код будет выглядеть примерно так:

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

Надеюсь, это поможет

1 голос
/ 04 июля 2011

Имя, которое вы даете изображениям, чисто условно.Я не думаю, что это проблема безопасности для раскрытия имен пользователей ваших пользователей.(Если это так, то вам лучше проверить свою CMS прямо сейчас!) Однако, если ваш сайт не полностью защищен, хакер может использовать SQL-инъекцию для доступа к вашим данным пользователя.

Но идея действительно далека-fetched.Вы можете продолжать использовать имена пользователей.: -)

IMO, просто назовите изображения как user-user_id.jpg (Здесь «пользователь» - обычная строка, за которой следует целое число - user_id)

1 голос
/ 04 июля 2011

Убедитесь, что имя пользователя правильно санировано, прежде чем использовать его как часть имени файла. Идентификатор пользователя должен быть сгенерирован системой, чтобы не вызывать проблем.

0 голосов
/ 04 июля 2011

Просто мои два цента. Если вы хотите добавить больше аватаров для пользователей на выбор, лучше использовать функцию типа uniqid () вместо пользователя. Иначе, вы можете делать все, что вам нравится.

Я использую MD5-хэш userid и time (). Просто вопрос предпочтений.

0 голосов
/ 04 июля 2011

Я обычно называю свои изображения случайной строкой, затем сохраняю ее в базе данных, прикрепленной к идентификатору загрузчика.Вы также можете хранить другие данные об изображении таким образом.

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

Таблица изображений

id |user_id |имя файла |и т.д.

0 голосов
/ 04 июля 2011

Достаточно уникального идентификатора пользователя, вам не нужно «имя пользователя».
Проблема не в этом, а в количестве файлов (в одной папке).
Разделите их на 1000 в папке (или на 100): возьмите первый, второй и третий символы строки идентификатора и поместите в отдельные каталоги:

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;
}
0 голосов
/ 04 июля 2011

нет огромного риска для именования файлов, как вы используете в первом примере, но чтобы сделать его более безопасным, почему бы вам не использовать что-то лучше, например

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

я думаю, что лучше избегать использования идентификаторов пользователей

...