Download cкрипт, чать 2. Нетривиальный контроль доступа. (+)

simplyAl

Guest
Download cкрипт, чать 2. Нетривиальный контроль доступа. (+)

Download скрипт для больших файлов (от 500метров) с контролем доступа.

Задача:
Сделать контроль доступа НЕ средствами апача, а отдавать файлы именно апачем. Версия апача 2.х. Если под 2.х вообще никак не удастся сделать, пусть будет 1.х – лишь бы работало.

Как это работает:

Есть БД, в которой есть строчка
Hash | filename | file_on_hdd | time_expire | count
SCO2ld7qHiV | MyAppOrWhatever.exe | file001.ext | 1113508529 | 0

Hash – хеш, тут все понятно
Filename – имя файла, которое нужно будет выплюнуть пользователю
file_on_hdd – реальное имя фала под которым он сохранен на диске
time_expire – время в будущем до которого открыт доступ
count – кол-во запросов к файлу

Имеет запрос от юзера:
/getfile.php?hash=SCO2ld7qHiV

На стадии контроля доступа проверяем:
1) Открыт ли еще доступ к данному файлу (поле в БД time_expire)
2) Не превышено ли кол-во запросов к данному файлу? Например, в настройках скрипта указывается, что к каждому файлу можно делать макс 100 запросов, после этого доступ закрывается.

Если файл доступен, то отдаем файл file001.ext с именем MyAppOrWhatever.exe через апач.

Почему отдавать через апач, а не через ПХП путем readfile() и т.д.?
Я пробовал отдавать через ПХП, скорость на больших файлов получается в несколько раз ниже, закачка произвольно отрубается на середине, апач начинает отжирать ОЗУ соразмерно объему файла (а файлы по 500 метров).

Если скачивать обычный статический файл (т.е. когда сам апач отдает файл «напрямую»), то все работает корректно - ОЗУ не жрется, скорость высокая, докачка работает (хотя и на ПХП докачку написать не проблема).

Почему ограничивать доступ не средствами апача?
Я не нашел такого модуля к апачу, который бы проверял expire файла по времени, кол-во запросов и брал данные из БД.

Идеи:
РАЗ: Написать модуль к апачу на перле. Теоретически можно написать модуль, относительно простой, который бы при запросе к файлу проверял его доступность и редиректил бы апач (но не юзера!, юзер не должен видеть прямой ссылки на файл) на реальный файл, попутно подставляя нужное имя файла юзеру в response-header.

НО: пока не могу разобраться как заставить работать перловые модули под Апач 2.0. ХЗ как там вообще что, опыт написания модулей небольшой….

ДВА: ПХП+simlinks+htaccess(?)
Предположим, параллельно с созданием строчки в базе, еще и создаем симлинк в директории доступной через веб:
/www/get/<hash>/<filename> -> /<file_on_hdd>
Т.е. в нашем случае:
/www/get/SCO2ld7qHiV/MyAppOrWhatever.exe -> /file001.ext

Теперь каким-то образом нужно сделать так, чтобы все запросы, которые идут внутрь /www/get/*, попадали туда только если некий скрипт get.php вернет «ОК».

Т.е. юзер обращается на http://www.mysite.com/get/SCO2ld7qHiV/MyAppOrWhatever.exe

Реально же пускается скрипт get.php, который проверяет доступ и если все хорошо, то говорит апачу «ОК» (не представляю как это реализовать:)) и апач отдает файл через симлинк.

В общем, такие вот у меня размышления, пока реально ничего сделать не удалось кроме раздачи файлов через ПХП путем чтения и echo контента, что не есть приемлемый вариант.
 

Nimous

Guest
Приколись.
Алгоритм следующий:
1. Файл лежит в запертой директории (напр. http://site.com/downloads/):
.htaccess :
<FilesMatch "*">
Order Allow Deny
Deny From All
</FilesMatch>
(или что-то вроде этого).

2. Обработчик пользовательского ввода находится
в любой другой директории (http://site.com/index.php)

3. Проверяем права на скачивание.

4. Если всё впорядке:
- ПЕРЕПИСЫВАЕМ .htaccess(!)
(а что помешает нам это сделать?):
Deny From All меняем на Allow From All, или, ещё лучше: Allow From ".getenv("REMOTE_ADDR")";
5. Отправляем хэдером.

6. Переписываем .htaccess обратно.

Ну как? Достаточно нетривиально? :)
 

Nimous

Guest
tristram
Ну, человек ведь просил нетривиально...
 

tristram

Guest
Nimous
это скорее тупо чем нетривиально...
 

simplyAl

Guest
Nimous
в какой момент htaccess переписывается обратно?
 

Nimous

Guest
После того, как начнётся закачка :)

Как это узнать-вопрос номер два.

Наверное нужно просто какой-то тайм-аут установить между
посылкой заголовка на переадресацию и переписыванием .htaccess
 

simplyAl

Guest
Nimous
Плохое это все решение. Мне ведь еще нужно учитывать каждое обращение к файлу и увеличивать счетчик count в базе на 1. Ведь не по логам же это делать.
 

Nimous

Guest
А в чём проблема?

Ты ведь скриптом даёшь разрешение на скачивание.

Что тебе мешает посчитать, кому, когда и сколько :)
 

simplyAl

Guest
Nimous
.htaccess - это не решение.

Мне нужно чтобы на _каждый_ запрос клиента к файлу пускался php файл, т.к. нужно считать кол-во этих самых запросов. Да и вообще переписывание файлов, таймауты - это "коряво" все...

Контроль по времени очень просто сделать, хотя бы даже создавать директории с симнлинками на реальный файлы, потом cron'ом пускать скрипт каждый 10 мин, который будет удалять устаревшие директории - все просто. А вот как ограничить кол-во запросов к файлу?

Предположим доступ открыт на 7 дней, мне нужно что за жти 7 дней файл выкачало не 200 человек, а 1 человек, которому доступ и был открыт. Причем этот человек может быть с динамическим ИП, т.е. контрольпо ИП не подходит, контрольпо cookie тоже не подходит, т.к. чел может юзать download манагер. Остается только время + кол-во запросов.
 

Nimous

Guest
Да. Коряво.

Но если что - работать будет :)

С нетерпением ожидаю других идей...

-~{}~ 24.04.05 09:00:

Отдай ему некий ПАРОЛЬ...

(который будет действителен 7 дней)
 

simplyAl

Guest
Nimous
Да не будет работать. Для контроля по времени вообще не нужно использовать никаких htaccessов, а контроль по кол-ву запросов твой способ не обеспечивает....

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

Nimous

Guest
Да, это будет работать, только если необходимо
СРАЗУ отдать файл.

-~{}~ 24.04.05 09:50:

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

Я уже не говорю про статистику.
 

Фанат

oncle terrible
Команда форума
Мне нужно чтобы на _каждый_ запрос клиента к файлу пускался php файл, т.к. нужно считать кол-во этих самых запросов.
эти две вещи никак не связаны друг с другом
 

simplyAl

Guest
Nimous
я думаю ты полностью не понимаешь задачи...
 
Сверху