PHP: Позволяет пользователю загружать приобретенный файл ТОЛЬКО

Я рассматриваю проблему, позволяющую клиентам, покупающим у меня контент через PayPal. Я предлагаю несколько неосязаемых товаров. Когда кто-то завершит покупку для одного из этих товаров, они будут перенаправлены на целевую страницу – назовем ее «thank_you.php» – которая автоматически загрузит загрузку в очередь и позволит ссылку на загрузку очереди в случае, если она не будет начать автоматически. Это будет сделано путем передачи уникального идентификатора элемента на страницу загрузки («download.php»).

Этот метод по существу является имитацией лучших ответов этих потоков:

PHP генерирует файл для загрузки, затем перенаправляет

Сценарий PHP, позволяющий пользователям загружать файл с моего сайта, не раскрывая ссылку на файл на моем веб-сайте?

Тем не менее, я боюсь, что, как только пользователь на «thank_you.php», они смогут загрузить свой товар, а затем использовать Firebug (или equiv.) Для редактирования идентификатора элемента и загрузки другого другого элемента:

<a href="download.php/38a205ec300a3874c867b9db25f47c61">Download Here</a> 

в

 <a href="download.php/7c8ddc86c0e4c14517b9439c599f9957">Download Here</a> 

Мне нужны идеи и помощь от вас, ребята, которые намного лучше в этом, чем я: что (и как) я мог бы реализовать в качестве решения, которое все равно позволит одному и тому же клиенту получить доступ и досуг, но предотвратить эту манипуляцию?

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

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

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

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

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

Из вашего комментария также звучит так, как будто вы используете хеш для идентификации элемента на другой части вашего сайта, а это значит, что пользователи могут определять хэш элемента, просматривая источник на другой части вашего сайта. На данный момент ваша безопасность через неясность очень похожа на мою, используя кодовые слова (например, «рыба означает, что Джон, кошка означает« Лиза »), сплетничая с кем-то и говоря« рыба и кошка выдумывают », все, имея лист на стороне со списками, записанными, которые каждый может видеть. Похоже, вы просто пытаетесь скрыть имена файлов, чтобы люди не могли их угадать. Это известно как безопасность через неясность , и вы действительно не купите вас.

Большинство других ответов предполагают, что элемент существует, и он будет иметь несколько разных хэшей, указывающих на него (например, файл1, будет иметь hash1, hash2 и hash3, являющиеся действительными ссылками на него). В этом случае они создали несколько хэшей, и каждый хэш уникален для определенного пользователя +. Я думаю, что они также предполагают, что все на сайте вы ссылаетесь на элемент загрузки как item1 а не на hash1 , который звучит так, как будто вы делаете?

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

Мой оригинальный ответ:

Вам нужно будет хранить (быть в базе данных или переменной сеанса), какие элементы пользователь может получить, для каждого вы создадите уникальный случайный токен. Этот токен будет использоваться для идентификации купленного товара. Передайте токен на страницу, где они будут загружаться (либо в переменной сеанса, либо в POST-аргументе, либо в качестве последней опции в URL-адресе, то есть GET). На странице, когда вам нужно загрузить, вы будете запрашивать переменную базы данных / сессии, используя информацию о сеансе, чтобы идентифицировать клиента и переданный токен (однако вы его передали), и с этим извлекать файл для загрузки.

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


Теперь я упомянул пару альтернатив, а затем по характеру приведенных ответов, я думаю, вам понадобится более подробная информация о том, как это сделать.

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

Поэтому я возьму один из вариантов реализации, самый простой вариант.


 <?php //Oh, I'm in a PHP page... //check if there is not a session if (session_id() != '') { //Ok, there is no session, let's create one session_start(); } //Now we are sure there is a session //Let's store in the session the id of the file I want to allow to download $_SESSION['download'] = GetFileId(); //GetFileId will do some mambo jambo expecto patronum to return an id //The id will be 38a205ec300a3874c867b9db25f47c61 or something ?> 

Теперь на странице загрузки ….

 <?php //Oh, I'm in another PHP page... //check if there is not a session if (session_id() != '') { //no session? screw you, no download for you header('Location: sorry.php'); } else { //Now we are sure there is a session //Let's get from the session the id of the file I want to allow to download $id = $_SESSION['download']; //Now get the url to redirect to allow the download $url = GetUrl($id); //GetUrl will do some mambo jambo expecto patronum to return an url //Ok, now we are going to return that file... //So put the correct MIME type header('content-type: image/gif'); //if it is a gif... //Load the file $contents = file_get_contents($url); echo $contents; //That's the only output exit(); } ?> 

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


Полагаясь на это решение:

Это просто, легко реализовать. Но у него есть некоторые недостатки:

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

*: Скажите, что соединение было потеряно, и сеанс истек в клиенте. О нет, нам не нужны счастливые клиенты.

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

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

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