Защита от прямого скачивания для больших файлов

MagicGTS

Новичок
А почему бы не отдавать скрипту данные через GET? Создаешь в базе запись о закачке файла в которой будет описано что качать разрешено (это не принципиально, что хошь то и пиши) главное чтобы скрипт получив урл вытащил из него id закачки и поискал в базе, если нашёл-значит качать можно, не нашел : объект не найден.
 

gene_vbj

Guest
Я работал над такой же задачей
Хочу поделиться проблемами и тем, как я их решил
1. Делать SetEnvIf - как то ненадежно - User-Agent, Referrer можно подменить (пришлось отказаться)
2. Делать скрипт читающий и выкидывающий в поток содержимое пробовал, Но. при скачке с https:// сайта в некоторых версиях IE был облом - файл или битый качался, либо портилось имя, либо IE терял файл в своем кэше (глупо но факт)
3. Давать открытый доступ - очевидно нехотелось

Сделал следующее:
Хранилище файлов расположил вне дерева сайта, дабы не лазали.
Сделал временное хранилище которое чищу find'ом по крону, удаля все что старее некоторого времени
Когда человек хочет скачать файл, создаю во временном хранилище каталог $name=md5(time()) в нем создаю ссылку на реальный файл и переправляю пользователя туда
Тут уже можно .htaccess'ом перекрыть некоторые вещи, но это уже на свой вкус.
 

trigger

Guest
Имхо, очень хорошая идея.

-~{}~ 01.07.04 17:25:

только лучше md5(microtime());
 

feelsgood

Guest
Доброго времени суток всем.
Передо мной вот похожая задача стоит.
Необходимо клиентам выдавать виртуальные url на закачку. Т.е. что б они не видели откуда скачивается файл. И реализовать ограничие по количеству скачиваний и времени действия "мнимой"ссылки

Пока возникли такие идеи:
Чтобы не показывать ссылку можно читать файл в браузер. Вообщем то, что обсуждалось выше.
А в сессии записывать время и линк на этот файл, поставить счётчик на количество скачиваний.

Может у кого есть более рациональное решение данного вопроса.
 

MagicGTS

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

Dikobrazz

Guest
Автор оригинала: feelsgood
Необходимо клиентам выдавать виртуальные url на закачку. Т.е. что б они не видели откуда скачивается файл.
А зачем им ссылки выдавать то? Посадить куку и дать линк на сам файл, а в папку поместить htaccess с обработчиком:
Action checkinfo "/check.php?"
AddHandler checkinfo .pdf .zip .mp3

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

c0r0ner

Новичок
проще накопать антилич скриптов и посмотреть как там делается
 

Яро

бард-скальд
Dikobrazz
Юзер ломится к файлу, и запускает обработчик, который читает куку и дальше определяет дать добро на закачку или нет. Так на оракл-сате реализовано и не надо файлы прятать.
Хмм... А отдавать файл надо скриптом? Или мы передаем какое состояние апачу и он решает давать закачивать файл или нет?
 

CrazyHacKeRs

Guest
Originally posted by gene_vbj

Сделал следующее:

Когда человек хочет скачать файл, создаю во временном хранилище каталог $name=md5(time()) в нем создаю ссылку на реальный файл и переправляю пользователя туда
Какого плана ссылочку ты создаешь?
ln -s ... ???

Originally posted by
Dikobrazz


Юзер ломится к файлу, и запускает обработчик, который читает куку и дальше определяет дать добро на закачку или нет. Так на оракл-сате реализовано и не надо файлы прятать.
Что обрабочтки возвращать должен: код ответа, или что-то еще?
 

che

Guest
Защита от прямого скачивания для больших файлов
Originally posted by Dikobrazz
Юзер ломится к файлу, и запускает обработчик, который читает куку ...
То есть я как больной должен буду качать сотни метров через бродилку. А wget и прочее объявляем ересью. Ну ладно, я куку в wgete выставлю, не вопрос. А бедный забитый забытый необразованный юзер?
 

che

Guest
Даун-лоад менеджеры. Или речь идет о полном списке мне известных?
 

Яро

бард-скальд
che
Даун-лоад менеджеры. Или речь идет о полном списке мне известных?
Ну просто большинство известных мне умеют работать с куками взятыми из интеграции в браузер.

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

Кстати, бедные забитые и необразованные юзвери обычно юзают reget и ему подобных, и следовательно - читаем что я написал выше.

А совсем на крайняк можно передавать идентификатор сессии в URL.
 

che

Guest
Регет у меня пару раз вставал криво и с оперой не интегрировался. С ие в общем то нормально. Кроме того, систему я уже три раза как переставил, а опера прежняя, просто импортирую закладки. Со всеми вытекающими. в общем вариантов много. Не говоря уже о ненадежности самих кук. Мое мнение - вся инфа должна быть забита в url. Если инфы много - в базу, а в урл - ид. Но это мое мнение, и я его не навязываю.
>>Кстати, бедные забитые и необразованные юзвери обычно юзают reget и ему подобных, и следовательно - читаем что я написал выше.
Лично мной был забит не один юзер до состояния готовности юзать wget, правда с картинками. Мой случай не единичный.
>>Тем более есть ресурсы напрямую рассчитанные на то, что файлы берутся при помощи браузера
На них прям так и написано?
>>А совсем на крайняк можно передавать идентификатор сессии в URL
аминь! о чем речь и шла.
 

D!!!

Новичок
Я сделал по такому принципу, который указал desperado

У меня одна только проблема, когда нажимаю в броузере скачать с помощью FlashGet то он закачивает index.html, которого в принципе вообще не существует

ссылка на файл такого типа
http://domen/clients/download/15/
где 15 - id файла, написано с помощью модуля mod_rewrite.

когда же я просто скачиваю например Mozzilой, то он нормально качает и поддерживает докачку.
Может кто-то скажет почему не хавает файл FlashGet ?

-~{}~ 21.01.05 14:08:

Автор оригинала: D!!!
Я сделал по такому принципу, который указал desperado

У меня одна только проблема, когда нажимаю в броузере скачать с помощью FlashGet то он закачивает index.html, которого в принципе вообще не существует

ссылка на файл такого типа
http://domen/clients/download/15/
где 15 - id файла, написано с помощью модуля mod_rewrite.

когда же я просто скачиваю например Mozzilой, то он нормально качает и поддерживает докачку.
Может кто-то скажет почему не хавает файл FlashGet ?
И вообще в ИЕ огромный ГЛЮК:
если прервать закачку, то он у меня перестает одупляться, т.е. не ходит больше по ссылкам :) Такая вот штука MSIE :D
 

alexhemp

Новичок
Для FlashGet если есть в конце слеш - то он считает что это каталог и все что вернется считает index.html - ведь имени файла нет.

Если ему отдать имя через Content-Disposition: attachment; filename=имя файла
то все нормально.
 

D!!!

Новичок
Автор оригинала: alexhemp
Для FlashGet если есть в конце слеш - то он считает что это каталог и все что вернется считает index.html - ведь имени файла нет.

Если ему отдать имя через Content-Disposition: attachment; filename=имя файла
то все нормально.
Неправда, я именно так и делаю, вот код:
PHP:
$resume = true;
$speed_limit = 10240;

$running_time = 0;
$begin_time = time();

set_time_limit( 300 );

$f = fopen( $file, 'rb' );
if ( !$f )
{
	header( 'location: '.$cfg['root'].'/clients/files/' );
	exit;
}

$file_size = filesize( $file );
$file_date = date( "D, d M Y H:i:s T", filemtime( $file ) );
$offset = 0;

if ( isset( $_SERVER["HTTP_RANGE"] ) )
{
	if ( preg_match("/bytes=(\d+)-/", $_SERVER["HTTP_RANGE"], $range ) && $resume == true )
	{
		header( "HTTP/1.1 206 Partial Content" );
		$offset = $file_size - intval($range[1]);
	}
	else 
	{
		header( "HTTP/1.1 200 OK" );
	}
}
else
{
	header( "HTTP/1.1 200 OK" );
}

$data_start	= $offset;
$data_end	= $file_size - 1;
$etag		= md5( $file . $file_size . $file_date );

fseek( $f, $data_start );

header( "Content-Disposition: attachment; filename=".basename( $file ) );
header( "Last-Modified: ".$file_date );
header( "ETag: \"".$etag."\"" );
if( $resume ) header( "Accept-Ranges: bytes" );
header( "Content-Length: ".( $file_size-$data_start ) );
header( "Content-Range: bytes ".$data_start."-".$data_end."/".$file_size );
header( "Content-type: application/octet-stream" );

while( !feof( $f ) && ( connection_status() == 0 ) )
{
	print fread( $f, $speed_limit );
	flush();
	sleep(1);
	$running_time = time() - $begin_time;
	if( $running_time > 240 )
	{
		set_time_limit(300);
		$begin_time = time();
	}
}
fclose( $f );
 

alexhemp

Новичок
D!!!

Поробуй ссылки строить без слеша на конце. Может это баг такой во FlashGet.
 
Сверху