On the current website I'm working on, I've got a directory of files for users to download which would be really nice to have some security method other than obscurity ;)
I was wondering if there's any way to supply login information via PHP to htaccess as though a user were entering it.
Alternately, if anyone knows a better way to secure user downloads using PHP, that's also acceptable. All of my googling turns up "just use htaccess" which isn't really helpful, as from the non-savvy user's point of view, they have to log in twice every time they use the website.
My best guess at doing it exclusively with PHP is to store files above the web root, then copy them to a web accessible folder temporarily, but this seems highly inefficient and I couldn't think up any way to remove them after the download has finished.
Note: I don't own the server this is running on and don't have ssh access to it.
If files are not too big (Gb) you can always use readfile for file's download. In this mode you can check user's auth before, and if it's ok output file contents to user, otherwise send him to login page.
With this method you can put your files in protected (with .htaccess) directory so you can be sure that nobody who isn't authenticated can access them.
Why reinvent the wheel? Take a look at File Thingy, which is pretty easy to install and customise. If nothing else, you can study the source to learn how to perform the authentication step.
I think the first option is better.
I think I would either store them in a folder outside of the web root, or in a folder protected by .htaccess and then have a php script that checked if the user was logged in and allowed to download a file asked for. If he was, then just pass the file through to the user.
Example from linked page at php.net:
Example #1 Using fpassthru() with binary files
<?php // open the file in a binary mode $name = './img/ok.png'; $fp = fopen($name, 'rb'); // send the right headers header("Content-Type: image/png"); header("Content-Length: " . filesize($name)); // dump the picture and stop the script fpassthru($fp); exit; ?>
Someone else made a comment about having to report the correct content-type, which is true. Often, in my own experience, I already know it, or can use the file extension pretty easily. Otherwise you can always try to have a look at finfo_file. On that page there are also some comments about what you could do especially for images as well.
you should use a php script to control the access. create a dir outside the webroot or inside the webroot with a .htaccess where you location the download files.
outsite the webroot is better.
you have to make sure that no one can access those files if they are located inside.
then take from the pear class lib. the class http_download.
using this class has many advantages.
you should not use readfile oder any forwarding filepointer because you have to set the headers yourself and the don't support http "range".
for the access restrictions you can use you session-manager, password, framework, forum etc.
pear - http_download http://pear.php.net/package/HTTP_Download
you need to copy the url, because SO encodes it to url-encoded string (which is correct), but PEAR-homepage doesn't like that.
Use X-SendFile
! There's extensions for Apache, Lighty and Nginx so there's a good chance there's one for your webserver.
Once you have the extension installed, you can authenticate the user using your PHP script, and then add the header:
header('X-SendFile','/path/to/file');
When your PHP script is done, it will trigger the webserver to stream the file for you. This is especially efficient if you use PHP along with for example FastCGI, because it frees up the PHP process for other work.
Evert