Password protected directory and files in PHP

2019-03-16 17:52发布

问题:

Im creating a simple private page with links to some files to download. I've done it with simple session management but I have a problem: if somebody click on the file-url he can download the file without the authentication. So what I can do to avoid this? I can make a HTTP Authentication but I want a custom login form and not the window popping out.

Any idea?

Thanks

回答1:

I guess it's a little bit late to answer. Anyway, it may help other people.

To protect files from direct downloads, you have to use a combinaison of PHP + .htaccess.

Let's admit that ./downloads/ is the folder where you store files you want to be downloaded. First, you have put .htaccess in this folder.

.htaccess in ./downloads/ :

deny from all

This will protect the folder to everybody, except scripts wich are executed on the server side.


Here is an example of a PHP script you can write at the root directory ./

index.php in ./ :

<?php
    if(!empty($_GET["filename"]))
    {
        //Here is the path to the folder containing files to download
        $my_download_folder = "./downloads/";

        //Preparing headers
        header("Content-type: application/force-download"); 
        //You can use more headers :
        //header("Content-Length: ".filesize($my_download_folder . $_GET["filename"]));
        //header("Content-Disposition: attachment; filename=".basename($my_download_folder . $_GET["filename"]));

        //You can check if the file does exist
        //if (!file_exists($my_download_folder . $_GET["filename"])) 
        //exit(); 

        //Reading file will trigger download on the browser side
        readfile($my_download_folder . $_GET["filename"]);
    }
?>

<html>
    <form action="" method="GET">
        <input type="text" name="filename" id="filename" />
        <input type="submit" value="Download It !" />
    </form>
</html>

This script is usable as it is. But be careful. Actually there is a major vulnerability : With this form you can download any file of the server (including a file like config.php which contains access to your database). To fix that vulnerability you can use IDs :

if ($_GET["id"] == 1)
    $filename = "toto.pdf"
if ($_GET["id"] == 2)
    $filename = "fish.png"



It provides a good example of protecting files from direct download but not from PHP download.



回答2:

The top answer is definitely the way to protect other people from viewing the directory directly, but there's a better way to fix the PHP download vulnerability:

if (isset($_GET['filename']) && basename($_GET['filename']) == $_GET['filename']) {

    // the author's code
    $my_download_folder = "./downloads/";

    header("Content-type: application/force-download"); 

    filename=".basename($my_download_folder . $_GET["filename"]));

    readfile($my_download_folder . $_GET["filename"]);

} else {
    // shoot back an error if the file that user wants to download is not permitted
}

So just wrap around his PHP code with this if/else statement to prevent others from exploring your server.



回答3:

Here is a very simple solution using htpasswd (quick and easy and it works).

$ cd /path/to/password_protected_dir
$ vi .htaccess

Then within your .htaccess file you will need to add this:

AuthUserFile /path/to/.htpasswd
AuthGroupFile /dev/null
AuthName "My Private Directory"
AuthType Basic

<Limit GET POST>
require valid-user
</Limit>

Next you will generate the .htpasswd file which you just included in the .htaccess file as show above. You can do this like so:

$ htpasswd -c .htpasswd user_name

At this point you will be prompted to enter the password.

Of course, this is merely one method of accomplishing this.



标签: php security