Ограничение загрузки файлов - PullRequest
4 голосов
/ 17 октября 2008

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

После совершения покупки клиент должен перейти на страницу, содержащую ссылку для скачивания, а также получить электронные письма, содержащие ссылку для скачивания, и электронное письмо с информацией об учетной записи, которая будет создана для них быть в состоянии загрузить с панели управления своей учетной записи). Я пытаюсь понять, как я могу скрыть / скрыть местоположение файла на моем сервере, чтобы один человек, который его купил, не мог просто скопировать и вставить прямую ссылку на файл в другом месте. Даже если я сделаю запрос на загрузку файла, ссылка в формате http://example.com/blah/download/454643, URL, который не соответствует фактическому местоположению файла, я думаю, все еще возможно найти файл на сервере? Я не очень понимаю, как работают разрешения на моем сервере, вот почему я спрашиваю. Заранее спасибо:)

Ответы [ 8 ]

8 голосов
/ 17 октября 2008

Вы в основном не предоставляете пользователям прямой URL-адрес файла. Серверные разрешения здесь не имеют никакого отношения.

Скажем, у вас есть необходимые файлы, сохраненные в /data/files/file.pdf (хорошая практика для хранения файлов вне вашего веб-корня). Вы можете предоставить пользователям ссылку для скачивания, которая выглядит примерно так: /download.php?auth=32

Когда пользователь нажимает на ссылку, download.php проверит, аутентифицирован ли сеанс / cookie-файл и действителен ли идентификатор загрузки (в случае, если у вас истек срок загрузки на основе времени) Затем download.php прочитает нужный файл с его местоположения и отправит его в браузер с соответствующими заголовками для принудительной загрузки.

5 голосов
/ 17 октября 2008

Храните файлы вне корневого веб-каталога, но затем убедитесь, что папка, в которой они хранятся, находится в директиве open_basedir в файле php.ini, это позволит вам получить к ним доступ из сценария PHP. Хранение их вне веб-корня означает, что к ним никогда не будет прямого доступа через HTTP.

Имейте PHP-скрипт, подобный приведенному в этих ответах, который может передавать / считывать файл. Если это большой файл, вам может потребоваться изменить значение max_execution_time, чтобы учесть дополнительное время, которое потребуется сценарию для считывания файла. Этот скрипт позволит вам аутентифицировать пользователя и убедиться, что он заплатил за файл.

Поместите .htacces в папку со скриптом, который переписывает файл, запрошенный из этой папки, в переменную. Это создает впечатление, что они напрямую обращаются к файлу, а это не так. Лично я бы поместил в эту папку только один скрипт, чтобы все было просто. Итак:

http://www.yourdomain.com/files/expensive_song.mp3

фактически переписывается на:

http://www.yourdomain.com/files/download_file.php?filename=expensive_song.mp3

Удачи.

2 голосов
/ 17 октября 2008

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

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

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

Сгенерированный URL должен иметь Формат:

<Ури префикс> / / <метка-в-шестнадцатеричной> / <отн-путь> который выглядит как «yourserver.com/bf32df9cdb54894b22e09d0ed87326fc/435cc8cc/secure.tar.gz"

- это MD5

  1. секретная строка (предоставляется пользователем)
  2. (начинается с /)
  3. <метка времени в-шестнадцатеричной>

Как видите, токен не связан пользователю вообще. Единственное ограничение фактор является меткой времени, которая используется лишить законной силы URL после данного Тайм-аут (secdownload.timeout).

1 голос
/ 18 ноября 2011

Некоторые веб-серверы, такие как Lighty и Nginx, реализуют заголовок X-Sendfile. Допустим, у вас есть приложение Django, ваше представление может вернуть заголовок X-Sendfile, который указывает на файл, который вы хотите отправить. Затем lighttpd будет обслуживать этот файл.

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

Это гораздо лучше, чем обслуживать статические файлы из вашего приложения. Веб-сервер оптимизирован для статических файлов и будет работать быстрее и значительно экономить ресурсы. Если вы обрабатываете несколько запросов, вам следует рассмотреть возможность использования X-Sendfile.

Здесь довольно хороший пост в блоге:

http://blog.zacharyvoase.com/2009/09/08/sendfile/

Инструкции Lighttpd / PHP можно найти здесь:

http://redmine.lighttpd.net/wiki/1/X-LIGHTTPD-send-file

Инструкции NGINX можно найти здесь:

http://wiki.nginx.org/XSendfile

Похоже, что существует ранний выпуск мода Apache, который делает то же самое:

https://tn123.org/mod_xsendfile/

1 голос
/ 17 октября 2008

Вот пример кода того, что я сделал для чего-то очень похожего:

// $mimeType is the mime type of the file
header('Content-type: ' . $mimeType);
// this will get the size of the file
// (helps for giving the size to the browser so a percent complete can be shown)
header('Content-length: ' . (string) (filesize($path)));
// disposition is either attachment (for binary files that can't be read by the browser) 
// or inline (for files that can be read by the browser
// some times you have play with this to get working so users get the download window in all browsers
// original filename is the name you want to users to see 
// (shouldn't have any special characters as you can end up with weird issues)
header('Content-Disposition: ' . $disposition . '; filename=' . $originalFilename);
// the next 2 lines try to help the browser understand that the file can't be cached
// and should be downloaded (not viewed)
header('Pragma: Public');
header('Cache-control: private');
// this will output the file to browser
readfile($path);

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

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

1 голос
/ 17 октября 2008

У вас может быть URL, который будет кодом авторизации для покупателя. Вы заставляете ее снова войти в систему, проверить, к какому файлу относится код, а затем передать ей файл. Вот пример кода PHP от osCommerce (я писал это давным-давно).

// Now send the file with header() magic
  header("Expires: Mon, 26 Nov 1962 00:00:00 GMT");
  header("Last-Modified: " . gmdate("D,d M Y H:i:s") . " GMT");
  header("Cache-Control: no-cache, must-revalidate");
  header("Pragma: no-cache");
  header("Content-Type: Application/octet-stream");
  header("Content-disposition: attachment; filename=" . $downloads['orders_products_filename']);

  if (DOWNLOAD_BY_REDIRECT == 'true') {
// This will work only on Unix/Linux hosts
    tep_unlink_temp_dir(DIR_FS_DOWNLOAD_PUBLIC);
    $tempdir = tep_random_name();
    umask(0000);
    mkdir(DIR_FS_DOWNLOAD_PUBLIC . $tempdir, 0777);
    symlink(DIR_FS_DOWNLOAD . $downloads['orders_products_filename'], DIR_FS_DOWNLOAD_PUBLIC . $tempdir . '/' . $downloads['orders_products_filename']);
    if (file_exists(DIR_FS_DOWNLOAD_PUBLIC . $tempdir . '/' . $downloads['orders_products_filename'])) {
      tep_redirect(tep_href_link(DIR_WS_DOWNLOAD_PUBLIC . $tempdir . '/' . $downloads['orders_products_filename']));
    }
  }
0 голосов
/ 17 октября 2008

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

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

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

Время: когда кто-то покупает файл у вас, сообщите ему, что он сможет загрузить файл только за 1 день или что-то подобное. Да, другие люди могут загрузить файл в течение этого дня, но только в течение 1 дня. Вы также можете установить ограничение на скачивание, чтобы они могли загружать его только 5 раз (это нормально).

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

Кажется, и то и другое можно легко использовать одновременно.

В любом случае (или в обоих случаях) будьте готовы обращаться с клиентами, которые не загрузили файл вовремя или хотят получить его снова по истечении определенного времени (или с другого компьютера / IP-адреса (некоторые люди не получают статичные)). Они не захотят платить снова, и, вероятно, не должны будут.

0 голосов
/ 17 октября 2008

Множество URL-адресов загрузок, которые я видел, основанных на покупке, как правило, используют некоторые guid и другую динамическую информацию в качестве части url, чтобы не упростить выбор одного идентификатора. Вы можете в конечном итоге использовать guid / datetimepurchased / id или что-то подобное в качестве части пути.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...