Home > Software design >  Deny direct file download from webserver by URL
Deny direct file download from webserver by URL

Time:09-23

I have a website where users can login and are identified by sessions and $user[id]. They can upload files. Files are stores in htdocs/uploads. Every file data is stored in a table to have a link between filename, location and user_id. On some places on my website i give the possibility to download the file by: <a href="' . $row['path'] . '" target="_blank" download>Download file</a>.

Behind $row['path'] a URL like domain.com/uploads/filename.jpg is given. If the user know this URL path he can download the file also without login or identification by entering the URL into a browser. I want to avoid this. How can i ensure, that only files can be downloaded from htdocs/uploads by click on such a download link on my website.

=> I am not able to create a folder outside htdocs
=> I have tried to change the folder permissions but w/o success
=> My website is basically made in PHP, a solution in PHP is prefered.

Any idea/help available? Thank you!

CodePudding user response:

You will need to go down the route of making PHP serve the file for you. This will ensure that you can validate user credentials before serving the file.

See examples on php.net here. This will explain how to serve files from PHP using header(). This answer also outlines some of the key concepts.

Once you've done this, you can deny direct access to these files using htaccess rules. This will ensure users can only access the files via the php endpoints, and those endpoints can perform validation of the user's credentials.

CodePudding user response:

First of all, don't store files in a public accessible folder. Store them below 'htdocs'. Then you need to write a function which delivers the file by a given id. Since you store the file information in the database, you can control 'who' is downloading the file in the function. The html would then look something like

<a href="/download/' . $row['file_id'] . '" target="_blank" download>Download file</a>

CodePudding user response:

I have solved it by doing following:

  1. Added a .htaccess file in my folder htdocs/uploads with following content:

<FilesMatch ".*">
    Order Allow,Deny
    Deny from All
</FilesMatch>

  1. Created a file: file_download.php with following content:

// Doing here some user verification based on the session and user_id
if($user['id'] != 'something i want to be') {
die('Not allowed to download this file'); 
} else {
// Verify the download as requested
    // Basic file name
    $file = basename($_GET['file']);

    // Path where the file should be stored
    $file = 'uploads/'.$file;

    if(!file_exists($file)){ // file does not exist
        die(''.$file.' file not found');
    } else {
        header("Cache-Control: public");
        header("Content-Description: File Transfer");
        header("Content-Disposition: attachment; filename=$file");
        header("Content-Type: application/zip");
        header("Content-Transfer-Encoding: binary");

        // read the file from disk
        readfile($file);
    } 
}

  1. Changed the download link from <a href="' . $row['path'] . '" target="_blank" download>Download file</a> to <a href="file_download.php?file=<?= $row['path'] ?>Download</a>

This way is blocking any try to download a file by using clear URL in the browser. the file can only be downloaded by having a user identification and the provided link from my website. If someone does not need the user verification, just delete the first if/else in the file_download.php.

  • Related