Как я могу хранить изображения частных пользователей в файловой системе и не нарушать их конфиденциальность?

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

Я принял решение хранить их в CDN, как это делает Facebook. Но как я могу гарантировать, что кто-то не сможет взломать чужую конфиденциальность, просто переделав URL и заменив случайные символы?

Например: предположим, у меня есть два изображения в моей файловой системе CDN,

Загружено пользователем1-
https://somecdnlink.com/somelocation/1234abc-5678pqr.jpg

Загружено пользователем2-
https://somecdnlink.com/somelocation/1234abc-5679pqr.jpg

Теперь user2 после загрузки своего изображения решил проверить URL изображения. Изображение, которое они только что загрузили, выскочило, открывая место, где оно хранится.
Затем он решает проверить, что произойдет, если он уменьшит число 9 и напишет 8 в этом месте.

Это автоматически откроет изображение пользователя user1, которое он сохранил на сервере cdn и должно быть закрытым.

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

Изображения могут быть очень большими, и может существовать около миллионов таких изображений.

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

Кроме того, хранение в базе данных лучший вариант в таком случае, а не cdn?

Я использую php и mysql.

3

Решение

Вы можете использовать один из следующих методов

1. Безопасность через неизвестность (Не рекомендуется, но просто!)

Создание достаточно большого хеш-префикса (например, произвольного 64-символьного алфавита) и его энтропия будет избыточным для любого текущего метода брутфорсинга. Если кто-то все еще находится в аду, могут возникнуть другие проблемы, о которых вам следует беспокоиться.

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

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

2. Поток файла через php, (Рекомендуется, требуется дополнительное кодирование)

Как правило, всякий раз, когда доступ к неисполняемому файлу осуществляется через Apache, он просто начинает вывод содержимого файла с соответствующим заголовком. Но если доступ к исполняемому файлу (модули для которого были загружены Apache), вместо непосредственного вывода файла, Apache отправляет запрос на выполнение соответствующему модулю, и как только модуль завершает выполнение сценария, он отправляет обратно вывод в Apache, который в свою очередь отправляется клиенту.

Здесь вы можете сделать .php файл, который обрабатывает весь доступ к файлу, и внутри него вы можете выполнить все проверки подлинности / авторизации, которые вы хотите выполнить, и как только владелец подтвердил, что вы можете отправить файл через php, как показано ниже.

// After validating the user is logged-in and is the rightful owner of the said file.

// the file you want to send, the user doesnt need to know this, it could we outside of the webroot too, just make sure php has access to it.
$path = "secret/path/to/the/file/to/be/downloaded";

// the file name of the download
$public_name = basename($path);

// get the file's mime type to send the content type header
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $path);

// send the respective headers
header("Content-Disposition: attachment; filename=$public_name;");
header("Content-Type: $mime_type");
header('Content-Length: ' . filesize($path));

// stream the file
$fp = fopen($path, 'rb');
fpassthru($fp);
exit;
2

Другие решения

Вы можете просто использовать имя хэша sha1 следующим образом:

$salt = "MySecretSalt";
$filename = sha1($username.$salt.microtime());

Затем у вас будет имя файла длиной 40 символов.

-2