Сервис документов для руководства: как мы построили защищённое файловое хранилище за 3 месяца
Бизнес запросил сервис для учёта и обмена документами высшего руководства. Функционал — как у Google Drive: вложенные папки, обмен доступом, поиск, избранное, корзина. Но с жёсткими требованиями по безопасности: шифрование файлов, сессия на 1 час, авторизация через наш сервис. Мы выбрали Laravel, PostgreSQL и DocumentDB (позже MongoDB) для хэшей, подключили WebSockets для real-time. Проект сдали в срок — бизнес успешно пользуется.
Контекст: запрос на защищённый документооборот
На проекте, где мы уже отвечали за сквозную авторизацию и сервис рассылок, поступил новый запрос от бизнеса.
Задача: создать сервис для учёта и обмена документами высшего руководства.
Требования к функционалу:
-
Создание вложенных групп (директорий) до бесконечности.
-
Размещение файлов и архивов в группах.
-
Обмен доступом — как к отдельным файлам, так и к группам.
-
Быстрый поиск по названию.
-
Фильтры: по общим файлам, по типам файлов, по размеру и т.д.
-
Добавление файлов и директорий в избранное.
-
Удаление в корзину с возможностью полной или частичной очистки.
-
Авторизация через наш сервис авторизации. Для руководства сервис должен быть первым в списке.
-
Сессия живёт только 1 час с отображением времени до логаута.
-
Комментарии к файлам, папкам от всех, кто имеет доступы.
-
Реакции на комментарии.
Требования к безопасности:
Все файлы должны быть зашифрованы. Если злоумышленник получит доступ к файлам — он не должен получить их содержимое.
Срок: 3 месяца.
Функционал: что значит «схожий с Google Диском»
Чтобы читатель понимал масштаб, опишем функционал Google Диска, который нужно было воспроизвести.
Google Диск — это облачное хранилище с широкими возможностями :
-
Хранение и организация файлов — загрузка, создание папок, вложенная структура без ограничений по глубине.
-
Обмен доступом — настраиваемые разрешения (просмотр, комментирование, редактирование) как для отдельных файлов, так и для папок .
-
Поиск — быстрый поиск по названию, типам файлов, дате изменения и другим параметрам .
-
Избранное — отметка файлов и папок для быстрого доступа.
-
Корзина — удалённые файлы попадают в корзину с возможностью восстановления или окончательного удаления.
-
Совместная работа — доступ для нескольких пользователей, общие диски для команд .
Нам нужно было реализовать этот функционал, но с акцентом на безопасность и закрытый контур для руководства.
Архитектура: Laravel, PostgreSQL и MongoDB
Мы выбрали стек, который позволял быстро разрабатывать и обеспечивал нужный уровень безопасности.
Laravel — фреймворк разработки
Стандартный выбор для проектов, где важна скорость разработки и надёжность. Laravel дал нам:
-
готовую систему аутентификации и авторизации;
-
удобную работу с очередями (для шифрования и обработки файлов);
-
экосистему пакетов для шифрования файлов .
PostgreSQL — основная СУБД
В PostgreSQL мы хранили структуру и характеристики файлов:
-
иерархию директорий;
-
метаданные файлов (название, размер, тип, дата загрузки);
-
права доступа;
-
избранное и корзину.
PostgreSQL обеспечивал быстрый поиск и фильтрацию — именно то, что требовалось для «быстрого поиска по названию и фильтрам».
DocumentDB (позже MongoDB из-за ограничений внутреннего контура) — для хэш-сумм и ключей
Для безопасности файлов мы использовали шифрование. Каждый файл шифровался секретным ключом.
В DocumentDB (позже мигрировали на MongoDB) мы хранили:
-
хэш-суммы зашифрованных файлов;
-
уникальные ключи — не те, которыми шифровали, а для связи с данными в PostgreSQL.
Почему MongoDB, а не S3:
По скорости работы с файлами MongoDB обходила S3 в нашем сценарии. Это было важно, потому что сервис должен был «быстро отрабатывать» — файлы руководства должны открываться без задержек.
Важно: мы не хранили сами файлы в MongoDB. Только хэши(итог шифрования содержимого файлов) и ключи для связи, а метаданные — в PostgreSQL.
Безопасность: шифрование и короткая сессия
Безопасность была ключевым требованием. Мы реализовали два уровня защиты.
1. Шифрование файлов
Каждый файл шифровался секретным ключом. Если злоумышленник получал доступ к файловому хранилищу, он видел только зашифрованные данные.
Для реализации мы использовали подходы, аналогичные пакетам для Laravel, которые шифруют файлы потоково (streaming), не загружая их целиком в память . Это важно для больших файлов и архивов.
Схема:
-
Пользователь загружает файл.
-
Файл шифруется секретным ключом.
-
Зашифрованный файл сохраняется в хранилище.
-
Хэш-сумма и уникальный ключ сохраняются в MongoDB.
-
Метаданные (название, размер, права) — в PostgreSQL.
При скачивании файл расшифровывается и отдаётся пользователю.
2. Сессия на 1 час
Для руководства сессия жила только 1 час. В интерфейсе отображался таймер до логаута.
Это дополнительная мера безопасности: даже если устройство оставили без присмотра, сессия истечёт через час.
Real-time: WebSockets для изменений
Мы подключили WebSockets для трансляции изменений в режиме реального времени.
Что это дало:
-
Если пользователь поделился файлом с коллегой — тот видит новый файл без перезагрузки страницы.
-
Если файл удалён или перемещён — изменения отражаются у всех, у кого есть доступ.
-
Совместная работа становится отзывчивее.
Фронтенд: Vue.js
Фронтенд реализовали на Vue.js. Это дало:
-
быстрый отклик интерфейса;
-
удобную работу с вложенными директориями и файлами;
-
интеграцию с WebSockets для real-time обновлений.
Результат: сдали в срок, бизнес пользуется
Проект был реализован в обозначенные 3 месяца. Сервис запущен, бизнес успешно им пользуется.
Стек
-
Backend: Laravel (PHP)
-
Основная СУБД: PostgreSQL
-
Хранение хэшей и ключей: DocumentDB (позже MongoDB)
-
Real-time: WebSockets
-
Frontend: Vue.js
Что мы вынесли из этого проекта
1. Безопасность — это архитектура, а не надстройка
Шифрование файлов, короткая сессия, разделение хранения данных (метаданные в PostgreSQL, хэши в MongoDB) — всё это закладывалось на этапе проектирования, а не добавлялось потом.
2. Сжатые сроки возможны, если требования чёткие
3 месяца — немного для такого функционала. Но чёткие требования и правильный выбор инструментов позволили уложиться.
3. MongoDB для хэшей — нестандартно, но оправдано
Обычно хэши хранят в той же БД, что и метаданные. Но в нашем случае MongoDB дала нужную скорость для связи файлов с ключами. Главное — не хранить в MongoDB сами файлы. Laravel же из "коробки" позволяет использовать несколько БД.
4. Real-time улучшает совместную работу
WebSockets сделали сервис отзывчивее. Пользователи видят изменения сразу, а не после обновления страницы.
Заключение
Этот проект — пример того, как функционал Google Диска можно реализовать в закрытом контуре с жёсткими требованиями по безопасности. Мы использовали привычные инструменты (Laravel, PostgreSQL, Vue.js) и добавили то, что требовалось для защиты данных руководства: шифрование, короткие сессии, разделение хранения.
Сервис работает. Бизнес пользуется. Сроки соблюдены.