David Doran Media

Search


Securing Your Downloads

Whether on a commercial project, a community project or a small personal project you will inevitably at some point need to restrict access to download files with a password, a login or some other authentication.

Here I will describe a very simple method to restrict access to the files using Apache(web server) and then grant access with PHP.

Sometimes as a hack solution developers will place files in random directories with random names and then have a PHP page invisibly redirect to the file. However, as you may have guessed if someone is determined enough this isn't really a solution and security through obscurity isn't much of a solution.

The solution

The answer is to use a .htaccess file and a PHP download file. (.htaccess files are special files which give Apache special instructions on how to serve files etc.)

Create a directory called "files". This will contain our files and our .htaccess
Put this in a .htaccess file in the directory:

Order Deny,Allow
    Deny from all
This will simply disallow all access to the "files" directory.

Next create a PHP called download.php, but place it in a folder outside files!

 
<?php
function send_download($filename, $display)
{
   if ( connection_status()!=0 )
   { return( False ); }
 
   //Make sure people don't 'inject' and try and change folders
   $filename = preg_replace( '@(\.\.|/)@', '', $filename );
   //File_exists will return true at a certain length, and may throw errors
   $filename = substr($filename,0,100);
 
   //binary/octet-stream
   header("Content-type: binary/octet-stream");
   header('Content-Disposition:attachment;filename="'.$display.'"');
   header("Pragma: public");
   header("Cache-control: private");
   header("Content-transfer-encoding: binary\n");
   header("Expires: 0");
   header("Pragma: no-cache");
   header("Content-length: ".filesize($filename)."");
 
   readfile( $filename );
 
   $status = (connection_status()==0);
   return($status);
}
 
//Check if they are allowed to download the file!!
$can_dl = true;
//You can put any user-check code in here
if( $can_dl == true )
{
        $file = isset($_GET['f'])?($_GET['f']):('');
        if( $file!='' )
        {
                $file = 'files/'.$file;
                //Send the download to them!
                send_download( $file ,$file );
        }
}
 

Now, by accessing the page download.php?f=demo.exe for example it would send you the file "files/demo.exe" if the user is allowed.

For you the important part is the "if" statement:

 
//You can put any user-check code in here
if( $can_dl == true )
{
Replace the statement in here with a database user lookup, a password check or even an IP check to verify the user has permission to download the file they want.