File Download Limit

I am currently creating a website for a client, which will mainly include the sale of various files. This is certainly a very common thing that makes me feel stupid without thinking about the method for this.

After making a purchase, the customer must be delivered to a page containing a download link, and also receive emails containing a download link and an email with information about the account that will be created for them (they will also be able to download from the control panel account). I am trying to figure out how I can hide / hide the location of a file on my server so that one person who buys it cannot just copy and paste the direct link to the file elsewhere. Even if I make a request to download the file with a link in the format http://example.com/blah/download/454643 , a URL that does not match the actual location of the file, I think you can still find the file on the server? I do not know much about how it is allowed to work on my server, and therefore I ask. Thanks in advance:)

+4
source share
8 answers

Basically you do not provide users with a direct file URL. Server-based permissions are irrelevant here.

Say you have the file (s) saved in /data/files/file.pdf (good practice for storing files from your web root). You can provide users with a download link that looks like /download.php?auth=32

When the user clicks on the link, download.php verifies the authenticity of the session / cookie and if the download identifier is valid (in case you have the end time of the download based on time) then download.php will read the required file from its location and send it to browser with appropriate headers for forced download.

+8
source

Store the files on the side of your web root, but then make sure that the folder in which they are stored is located in the open_basedir directive in the php.ini file, this will allow you to access them from a PHP script. Saving them outside the root website means that they will never be directly accessible via HTTP.

Have a PHP script like the ones listed in these answers that can transmit / read a file. If this is a large file, you may need to change "max_execution_time" to the account for the extra time it takes the script to read the file. This script will allow you to authenticate the user and verify that they paid for the file.

Put .htacces in a folder with a script that overwrites the file requested from this folder with a variable. This makes it look like they are accessing the file directly, which is not the case. Personally, I would put a single script in this folder so that everything is simple. So:

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

really overwrites:

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

Good luck.

+5
source

If you have access to running Lighttpd, you should definitely check out the Mod_SecDownload module. I used this in a previous project that sold video and image files reliably.

Since the web server does not know anything about the permissions used in the application, the resulting URL will be available to every user who knows the URL.

mod_secdownload removes this problem by introducing a method of authenticating the URL for the specified time. The application must generate a token and timestamp, which is checked by the web server before it resolves the file that the web server will load.

The generated URL should have the format:

<Uri prefixes> / <marker> / <timestamp-in-hexa> / <Rel-path> which looks like "Yourserver.com/bf32df9cdb54894b22e09d0ed87326fc/435cc8cc/secure.tar.gz"

<token> is MD5

  • secret line (user provided)
  • (begin with /)
  • <timestamp-in-hexa>

As you can see, the token is not bound to the user. The only limitation factor is the timestamp, which is used to invalidate the URL after the specified timeout (secdownload.timeout).

+2
source

You may have the URL of the authorization code for the buyer. You force her to log in again, check which file the code is in, and then transfer the file to her. Here is a sample PHP code from osCommerce (I wrote this a long time ago).

// Now send the file with header() magic header("Expires: Mon, 26 Nov 1962 00:00:00 GMT"); header("Last-Modified: " . gmdate("D,d MYH: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'])); } } 
+1
source

Here is a sample code of what I did for something very similar:

 // $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); 

You can, of course, add any registration and registration to this to make sure that it does not download too many times.

Also, as mentioned earlier, make sure you place the file outside (or above) the web server root document so that people cannot determine the path. Or you can even enter a password in a directory so that only internal people can easily access the list of files, but would not recommend it. (Only do this if you can put something outside the root of the doc.)

+1
source

Some web servers, such as Lighty and Nginx, implement the X-Sendfile header. Say you have a Django application, you can return your view to the X-Sendfile header, which points to the file you want to send. Then lighttpd will serve this file.

The file may be in a place inaccessible to the Internet (this is not 301 redirects), and since your application serves the header, you can first authorize.

This is much better than serving static files from your application. The web server is optimized for static files, and it will be faster and much easier on resources. If you are processing multiple requests, you should use the X-Sendfile.

Here's a nice blog about him:

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

Lighttpd / PHP instructions can be found here:

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

NGINX instructions can be found here:

http://wiki.nginx.org/XSendfile

There is also an early release of Apache mod that does the same:

https://tn123.org/mod_xsendfile/

+1
source

The many purchase-based boot-based URLs I've seen tend to use some guidelines and other dynamic information as part of the URL, so as not to be as simple as guessing a single identifier. In the end, you can use guid / datetimepurchased / id or something similar as part of the path.

An additional option will be to ensure that the user is logged in before allowing the download to provide an additional level of security.

0
source

Well, first of all, you definitely do not want to refer directly to the file. You will probably want to send the user a link to the service you created (or even to the page) with the generated id argument, which will lead to the download of the file if certain criteria are met.

These criteria are complex, because you need to allow the user to download the file more than once (in case he cannot download the full file for the first time or delete it accidentally, etc.), but after that it works until you kill him.

I would suggest using time or IP to filter download requests.

Time: when someone buys a file from you, let them know that they can only download the file for 1 day or some of them. Yes, other people can download the file during this day, but only for 1 day. You can also set a download restriction, so they can only download it 5 times (this is normal).

IP: When someone buys a file from you, tell them that they can only download the file from this IP address. The download service can, of course, verify this when they try to download the file.

It seems that both of them can be easily used at the same time.

In any case (or both), be prepared to contact clients who did not download the file on time, or want to receive it again after the deadline (or from another computer / IP (some people do not get static)). They will not want to pay again, and probably should not.

0
source

All Articles