Правила форума Гаранты форума
Размещение рекламы AMX-X компилятор

Здравствуйте, гость Вход | Регистрация

Наши новости:

14-дек
24-апр
10-апр
11-апр

Файловый архив и временные ссылки

, Рубрика: Костыли от Gecko
Статус пользователя Gecko
сообщение 29.12.2021, 19:11
Сообщение #1
Стаж: 7 лет 4 месяца

Сообщений: 1247
Благодарностей: 518
Полезность: 346

Информация для размышлений и споров!

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

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

Суть: Генерировать хэши на удалённых серверах bash-скриптом и на интерфейсе пользователя (интернет магазин,
блог и любой другой сайт раздающий файлы)

К примеру, у меня есть один файловый сервер (обычный бюджетный VPS), на который происходит загрузка файлов.
На этом сервере установлен Linux, есть доступ по SSH, установлен веб-сервер nginx и всё.
Также есть 2 рабочих каталога, один для хранения файлов а другой для раздачи по http (то есть в этот каталог смотрит
nginx).

Код
input_dir='/opt/www/store.mysite.local' // для хранения файлов
output_dir='/var/www/store.mysite.local' // для раздачи по http (то есть в этот каталог смотрит
nginx)


Также на этом сервере, в задачах cron запущен 1 bash-скрипт (simlink.sh).
- cкрипт выполняет задачу 1 раз в 24 часа в 00:00, после чего все старые ссылки умирают и создаются новые.

ВАЖНЫЙ МОМЕНТ: Время на файловом сервере и на сервере где расположен сам сайт должно быть
синхронизировано.
В момент вывода ссылки пользователю на сайте желательно с помощью curl проверить доступность файла а уже потом показать ссылку пользователю либо сообщение о временных трудностях на сервере.
В среднем достаточно 5 секунд для генерации нескольких тысяч ссылок.

Задача скрипта получить содержимое каталога
Код
/opt/www/store.mysite.local
и создать на все файлы в этом каталоге
символьные ссылки в каталог куда смотрит nginx
Код
output_dir='/var/www/store.mysite.local'


Пример ссылки на файл /opt/www/store.mysite.local/cs1.6.exe
Код
/var/www/store.mysite.local/50f647eb4d2ac294845a81ebb189ba79/cs1.6.exe

а так ссылка выглядит в браузере
Код
http://store.mysite.ru/50f647eb4d2ac294845a81ebb189ba79/cs1.6.exe

это симлинк который расположен в каталоге
Код
/var/www/store.mysite.local


Вот содержимое моего скрипта с комментариями:
Код
#!/bin/bash

solt='F7b60vnYr' # Соль для наглядности
input_dir='/opt/www/store.mysite.local' # Каталог где будут лежать файлы
output_dir='/var/www/store.mysite.local' # Каталог символьных ссылкок

# Если каталог output_dir отсутствует, то создаём его
if [ ! -d "$output_dir" ]; then
mkdir -p $output_dir
fi

# Если каталог output_dir существует, то удаляем со всем его содержимым
if [ -d "$output_dir" ]; then
rm -rf $output_dir/*
fi

# Перебираем файлы в каталоге присвоенный переменной input_dir
for files in "$input_dir"/*
do
  # Убираем лишние пути и оставляем только имя файла
  file=`echo "$files" | sed "s/.*\///"`
  # Получаем md5-хеш на основе значений переменных и текущей даты(день,месяц,год) и убираем в конце "-"
  hash=`echo -n $(date +'%d%m%Y')$solt"$file" | md5sum | sed -e 's/  -//'`
  # Создаём каталог в виде хеша который мы получили выше и записали в переменную hash
  mkdir -p $output_dir/$hash
  # Создаём символьные ссылки
  ln -s $input_dir/"$file" $output_dir/$hash/"$file"
done


При таком подходе все файлы могут быть распределены по разным серверам а на сайте нужно только
указать имя файла "CS1.6.exe" при создании статьи или к примеру товара. Ещё можно выбрать файловый сервер store* чтобы
указать на каком сервере лежит файл, это если их у вас > 1.

А вот содержимое того что должно быть на интерфейсе (выдавать конечному пользователю)
В данном примере на php, показан процедурный подход генерации ссылки на интерфейсе.
В ООП создаёте необходимый класс в котором реализуете генерацию хеша по аналогичному принципу.

Интерфейс (просто пример)
Код
<?php
# Процедурный подход реализации примера

  $file_name='cs1.6.exe'; // Имя файла
  $store='https://store.mysite.ru/';
  $solt='F7b60vnY'; // Соль для примера
  $time=date('dmY'); // Дата
  $var=md5($time.$solt.$file_name); // Формируем хеш файла

       echo $var.'<br />'; // Выводим пример хеша
       echo '<br /><a href='.$store.$var.'>Download</a>'; // в виде готовой ссылки ссылки
    
?>


Из плюсов, генерация тысяч ссылок происходит за секунды без необходимости задействовать СУБД.
Файлы не хранятся там где и сам сайт а значит при компрометации сайта файлы не пострадают. А если сами файлы архивировать с парольной защитой то и на удалённом файловом сервере файлы будут в безопасности так как пароли на файлы лежат в БД сайта.
Такой подход также полезен для киносайтов с онлайн просмотром, где достаточно 2-3 сервера во главе с nginx в качестве балансировщика нагрузки а сами файлы синхронизируются между серверами с помощью rsync.

НЕМНОГО ТЕОРИИ
Варианты деплоя/загрузок файлов по серверам это уже другая история которая зависит от проекта, к примеру по FTP с закачкой только изменённых файлов, в рамках небольшого проекта деплой можно производить с помощью VSCODE
и
этого скрипта
Код
#!/bin/bash

FTP_DEPLOY_USER="user@example.com"  # FTP User
FTP_DEPLOY_HOST="ftp.example.com" # FTP Host

read -p -s "FTP Password:" FTP_DEPLOY_PASS;

FTP_DEPLOY_DEFAULT="app" # specify a source subfolder (./app)
FTP_DEPLOY_ROOT="" # specify a remote upload folder (/public_html)

ftpPath="${FTP_DEPLOY_DEFAULT}$1"
ftpCommand="open -u $FTP_DEPLOY_USER,$FTP_DEPLOY_PASS $FTP_DEPLOY_HOST;" # open FTP connection
ftpCommand="$ftpCommand set ssl:verify-certificate no;" # disable certificate verification
ftpCommand="$ftpCommand mirror -c --script=/dev/null --verbose=1 --parallel=3" # apply lftp mirror command with 3 parallel uploads

ftpCommand="$ftpCommand --exclude .c9/ " # exclude c9 settings folder
ftpCommand="$ftpCommand --exclude .git/ " # exclude .git folders
ftpCommand="$ftpCommand --exclude wp-admin/ --exclude wp-includes/ --exclude-glob wp-*.php" # exclude WP core
ftpCommand="$ftpCommand --exclude-glob *.zip --exclude-glob *.log --exclude-glob *.ini " # exclude .zip .log .ini
ftpCommand="$ftpCommand --exclude ftp_deploy.sh " # exclude this script

ftpCommand="$ftpCommand  -R ${HOME}/workspace/$ftpPath ${FTP_DEPLOY_ROOT}/$ftpPath "

echo "Changes ($ftpPath):"
lftp -c "$ftpCommand"

read -p "Procees with file sync? (y/n) " yn
while true; do
    case $yn in
        [Yy]* ) lftp -c "${ftpCommand/--script=\/dev\/null/ }";  break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done


Либо обычная загрузка файла в локальный каталог вашего WP к примеру загрузке файла выбираем локальный каталог store1 откуда скриптом загруженный файл переноситься на удалённый файловый сервер ftps://store1.mysite.ru/tmp а уже из каталога tmp этот файл уже местный скрипт переносит в каталог файлов.

Если файл был загружен слуйчайно, то просто загружаем новый с таким же именем, и указываем его на сайте и этот файл будет перезаписан. А если удалили статью то файл можно удалить автоматически с помощью специального скрипта который будет производить сверку из БД сайта с файлами в каталоге на удалённом сервере, получаем список файлов сайта и записываем его в store1.txt далее скриптом делаем в цикле сверку имеющихся файлов в каталоге с файлом который находиться в списке, если его там нет то удаляем.

Отредактировал: Gecko, - 29.12.2021, 20:49


Не отвечаю на ЛС.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
Поблагодарили 1 раз
   Цитировать сообщение
Marci
сообщение 29.12.2021, 20:19
Сообщение #2
Стаж: 4 года 4 месяца

Сообщений: 161
Благодарностей: 72
Полезность: < 0

Читать посты ТС'а можно понять, что насколько он самовлю и умнее всех. У меня все!
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя BaHeK
сообщение 30.12.2021, 13:31
Сообщение #3


Стаж: 17 лет

Сообщений: 571
Благодарностей: 505
Полезность: 651

Cкрытый текст


Чуть-чуть нарушаю
http://img-host.su/aoN1.png
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
Поблагодарили 1 раз
   + Цитировать сообщение
Статус пользователя Gecko
сообщение 30.12.2021, 15:24
Сообщение #4
Стаж: 7 лет 4 месяца

Сообщений: 1247
Благодарностей: 518
Полезность: 346

BaHeK, Согласен, lol.gif потому рубрику и назвал Костыли от Gecko. Но мне интересно, в чем этот метод плох? Аргументируй более развёрнуто, по сути тема для таких как ты и создавалась. Я постараюсь тебя удивить, и доказать что твой метод в конкретном проекте в разы хуже.

Отредактировал: Gecko, - 30.12.2021, 15:33


Не отвечаю на ЛС.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя BaHeK
сообщение 30.12.2021, 15:44
Сообщение #5


Стаж: 17 лет

Сообщений: 571
Благодарностей: 505
Полезность: 651

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


Чуть-чуть нарушаю
http://img-host.su/aoN1.png
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя Gecko
сообщение 30.12.2021, 16:51
Сообщение #6
Стаж: 7 лет 4 месяца

Сообщений: 1247
Благодарностей: 518
Полезность: 346

Цитата(BaHeK @ 30.12.2021, 15:44) *
Gecko, зачем вообще нужно раз в сутки менять общедоступные ссылки на скачивание файлов? есть хотя бы 1 проект, где общедоступные ссылки меняются каждые сутки?

Интернет магазин, продажа цифровых товаров.
Задача оградить контент манагера физически к всякому доступу к товару (файлу)
Всё что делает контент-манагер это вводит имя файла товара в специальное поле, ну и пишет контент для этого товара.
На самом сервере где расположен сайт физически нет никаких файлов товара. В базе данных тоже ничего нет, кроме вышесказанного названия файла.

Написан определённый класс который формирует ссылку на товара при его оплате
ссылка в шаблонизаторе имеет такой вид:
Код
<a class="purchase__name_link" href="{url_generator route="product" url=$purchase->product_hash->url}">{$purchase->product_name|escape}</a>


Суть в том что мы заранее знаем все хеши на файловых серверах, потому как знаем как они формируются
Код
$date.$sold.$product_name


То есть, файловый сервер не требует установки какого либо ПО кроме nginx и запуска в cron 1-2 скрипта.

По безопасности, на удалённый сервер файлы добавляет человек который имеет доступ к товарам, добавлять он их может в виде обычного деплоя (скрипт такого деплоя я привел), всё остальное скрипт на файловом сервере сделает автоматически.
Всё что нужно сделать этому человеку это сообщить имя файла с расширением контент-манагеру магазина, к примеру cs1.6.zip (это чисто пример)

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

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

Отредактировал: Gecko, - 30.12.2021, 17:26


Не отвечаю на ЛС.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя BaHeK
сообщение 30.12.2021, 22:18
Сообщение #7


Стаж: 17 лет

Сообщений: 571
Благодарностей: 505
Полезность: 651

За сутки клиент может поделиться ссылкой в соц. сетях и все желающие скачают твой архив.


Чуть-чуть нарушаю
http://img-host.su/aoN1.png
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя Gecko
сообщение 30.12.2021, 23:06
Сообщение #8
Стаж: 7 лет 4 месяца

Сообщений: 1247
Благодарностей: 518
Полезность: 346

Цитата(BaHeK @ 30.12.2021, 22:18) *
За сутки клиент может поделиться ссылкой в соц. сетях и все желающие скачают твой архив.

cbf1b2bfde1a.gif А что мешает ему поделиться скаченным (купленным) файлом на другом ресурсе?

Цитата(BaHeK @ 30.12.2021, 22:18) *
зачем вообще нужно раз в сутки менять общедоступные ссылки на скачивание файлов?


Чтобы файл нельзя было разместить на постоянной основе на других ресурсах - личерство.
Онлайн кинотеатры на пример.
К примеру по такому принципу работал некогда известный в Украине портал ex.ua
К стати, в этом году 6 октября Илья Мась умер (создатель и ведущий разработчик некогда популярных ex.ua и infostor.org

Отредактировал: Gecko, - 30.12.2021, 23:26


Не отвечаю на ЛС.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя csnet
сообщение 31.12.2021, 20:56
Сообщение #9
Стаж: 12 лет

Сообщений: 4808
Благодарностей: 3849
Полезность: 690

на пхп readfile, зачем велосипед.

Отредактировал: csnet, - 31.12.2021, 22:09


go v cs:go
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя Metal Messiah
сообщение 1.1.2022, 11:12
Сообщение #10


Иконка группы

Стаж: 13 лет

Сообщений: 2457
Благодарностей: 1482
Полезность: 770

HostGame.cf
Доброе утро. Как здоровье?

Идея с символьными ссылками неплохая. Это одна из десятков возможных реализаций подобной задачи.
А еще где-то был сервис с одноразовыми записками, при первом окрытии ссылки она становится невалидной. Название не помню.
Поливать ничем не буду, скажу только что более корректным было бы название symlink, а не simlink.

Цитата
на пхп readfile, зачем велосипед.
Товарищи, а вы понимаете вообще кто в связке nginx + apache или nginx + fpm будет отвечать за отдачу файла в случае, описанном Gecko, и при реализации через readfile / fpassthru? И у какого случая производительность будет выше? crazy.gif
И что вообще произойдет если 50 человек одновременно зайдут по ссылке (даже если разной)

Отредактировал: Metal Messiah, - 1.1.2022, 11:13


Полезные публикации - ссылки у меня в профиле. Ссылка на плагин против спама на сервере StopServerSpam там же.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
Статус пользователя Gecko
сообщение 1.1.2022, 15:00
Сообщение #11
Стаж: 7 лет 4 месяца

Сообщений: 1247
Благодарностей: 518
Полезность: 346

Metal Messiah,
Цитата
более корректным было бы название symlink, а не simlink.

good.gif Я также за аутентичность, но!
Прикрепленное изображение

Производительность моего примера безальтернативно выше и проще в масштабировании. Да обычный блогер с каким нибудь WP может оградить свой ресурс от многих проблем связанных с раздачей огромного числа файлов.
Сам же файловый архив можно масштабировать как угодно. Самый дешевый и эффективный способ с nginx
https://nginx.org/ru/docs/http/ngx_http_upstream_module.html

При этом синхронизацию файлов можно организовать как угодно, хоть скриптом проверять в каталоге TMP новый файл и по префиксу store4_CS1.6.zip отправлять этот файл на определённый в префиксе сервер, то есть на http://store4.mysite.ru/* либо на все сервера сразу. Либо через rsync. Далее вычислить контрольную сумму всех разделов с файлами на всех серверах и сверять их для подтверждения синхронизации.


Не отвечаю на ЛС.
Перейти в начало страницы         Просмотр профиля    Отправить личное сообщение
   + Цитировать сообщение
  Ответить в данную темуНачать новую тему
 
0 пользователей и 1 гостей читают эту тему: