Генерировать ip и ограниченную по времени ссылку для скачивания

#php #download

#php #Скачать

Вопрос:

существует прямая ссылка для загрузки файла. пользователи могут загрузить эту ссылку после выплаты, например:

 http://example.com/download/webapp.rar
  

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

 http://example.com/download.php?a5fds588fgdf
  

или

 http://example.com/download/a5fds588fgdf
  

есть ли какие-либо советы?

Комментарии:

1. «Без каких-либо баз данных»? Что это за требование? Вам абсолютно необходимо сохранить некоторые данные для решения этой проблемы, и база данных — лучшее место для этого. С какой стати вы пытаетесь избежать использования базы данных?

2. Без базы данных вы можете добиться этого cookies , установив их expiry . Однако проблема в том, что вы можете удалить файлы cookie. так что это ненадежный способ.

3. @GhazanfarMir … помимо того факта, что файлы cookie могут быть подделаны так легко, что они практически бесполезны для этого…

4. WTF так усердно работал над «отсутствием базы данных», что я не заметил «привязки к IP». Это ужасная идея. IP-адреса не являются фиксированными, и адрес, используемый для оплаты загрузки, и адрес, используемый для начала загрузки, не обязательно должны совпадать. Вот почему никто этого не делает . Типичная схема, которую я заметил, — ограничить количество загрузок до 5 или что-то в этом роде. Минимизируйте «пиявку», не полностью обманывая некоторых ваших законных пользователей.

5. @meagar Я не хочу использовать DB, потому что мой веб не управляется DB.

Ответ №1:

Для этого есть действительно хороший модуль nginx.

URL получает два параметра — назовем их s (безопасность) и t (временная метка). Безопасность — это безопасный хэш, созданный на основе метки времени, пути и соли (в вашем случае просто добавьте ip).

 $ip = $_SERVER['REMOTE_ADDR'];
$salt = 'change me cause im not secure';
$path = '/download/webapp.rar';
$timestamp = time()   3600; // one hour valid
$hash = md5($salt . $ip . $timestamp . $path); // order isn't important at all... just do the same when verifying
$url = "http://mysite.com{$path}?s={$hash}amp;t={$timestamp}"; // use this as DL url
  

Для проверки:

 $ip = $_SERVER['REMOTE_ADDR'];
$salt = 'change me cause im not secure';
$path = $_SERVER['REQUEST_URI'];
$hashGiven = $_GET['s'];
$timestamp = $_GET['t'];
$hash = md5($salt . $ip . $timestamp . $path);
if($hashGiven == $hash amp;amp; $timestamp <= time()) {
    // serve file
} else {
    die('link expired or invalid');
}
  

Теперь вам просто нужно переписать загрузки в этот «человек посередине»-скрипт, и все готово.

Пример перезаписи для nginx:

 location /download {
    rewrite ^.*$ /download.php last;
    break;
}
  

Я не очень хорошо знаком с перезаписями apache, поэтому вы можете проверить это самостоятельно.

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

Или вы просто используете модуль nginx secure link: http://wiki.nginx.org/HttpSecureLinkModule

Для lighty также есть кулон: http://redmine .lighttpd.net/wiki/1/Docs:ModSecDownload

Или модуль безопасной загрузки nginx: http://wiki.nginx.org/HttpSecureDownload

Может быть, есть что-то и для apache… Может быть, вы могли бы что-то сделать с перезаписями там…

Комментарии:

1. Это удивительный и блестящий способ выразить это! Спасибо!

2. @Hikaru-Shindo Спасибо, приятель, можешь ли ты добавить мою ссылку на образец в свой скрипт (для моего теста)

3. @NuLLeR Я переписал свой ответ в соответствии с вашим примером и добавил еще немного информации, которую следует учитывать.

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

5. Я обнаружил, что мне нужно добавить $path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ); , чтобы хэшированный путь в скрипте получателя не отображал переменные запроса и $timestamp <= time() должен быть $timestamp >= time()

Ответ №2:

Если вас не беспокоит, что люди могут декодировать некоторые параметры, такие как IP или временная метка, вы можете попробовать что-то вроде этого :

 <?php
$salt = 'SALTING'; // Hash cipher
$key = new stdClass();
$key->limit = time() 3600; // 1 hour limit
$key->ip = $_SERVER['REMOTE_ADDR'];
$key->security = sha1(sha1($salt.serialize($key))); // Double sha1 for fun

$key_param = base64_encode(serialize($key));

echo sprintf('http://mysite.com/download/%s', $key_param);
?>
  

Теперь это для получения уникального ключа, действительного 1 час, для ip $key-> ip.

Чтобы проверить это :

 <?php
$salt = 'SALTING';
$key = $_GET['key'];
$key = base64_decode($key);
$key = unserialize($key);
if($key->security != sha1(sha1($salt.serialize($key)) || $_SERVER['REMOTE_ADDR'] != $key->ip) {
    throw new Exception('Security breach. U mad bro ?');
}
?>
  

И все готово 🙂 База данных не задействована. После этого просто хеширование и сопоставление хэшей.

Но я думаю, что простое $_SESSION[$file_id] = time() 3600; решение поможет в одной строке…Хотя это не так весело.

Комментарии:

1. @Tom Спасибо, где я должен указать имя своего файла «webapp.rar » ?

2. @NuLLeR Ну, где я повторяю ваш URL?

3. @Tom — хорошо сказано! кратко и просто, я хотел добавить, что мы с моим партнером создали (немного более сложный, но!) сценарий аналогичного типа … (останется не упомянутым, потому что было бы грубо продвигать продукт здесь), но на самом деле мы вставили несколько фрагментов информации в $key, упомянутый Томомвыше. Добавление всевозможных возможностей, таких как проверка «реферера», потоковая передача (и это лишь некоторые из них;) и т.д… Будьте также осторожны с ограничениями url, поскольку ваши глаза расширяются до кодировки base64 практически для всего, что есть в этом URL 🙂

4. @Tom — также не забывайте проверять ограничение по времени на стороне проверки ($key-> проверка ограничения …)

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

Ответ №3:

Мой главный совет — использовать базу данных!

Но если вам абсолютно необходимо сделать это без этого, я бы предложил использовать библиотеку кэширования, такую как cache-lite: http://pear.php.net/manual/en/package.caching.cache-lite.intro.php

Многие фреймворки PHP (если вы их используете) также поставляются с библиотекой кэширования

Вы можете кэшировать назначенный вами IP и случайный ключ вместе с датой истечения срока действия (некоторые библиотеки кэша также позволяют назначать время действия кэша)