3

Lets say I want to make an application where users can upload private files to a laravel based website. I dont want to make their files available to public, but I want them to be able to download the files after they have logged in.

So I need to verify that they have logged in, and that they have the correct account ID to download a specific file. How can I create this restriction?

I have been looking around http://laravel.com/docs with no success, and with google search I was only able to obtain some vanilla PHP samples, but it seems messy to integrate into laravel, which way do you recommend me to do this?

I may be overcomplicating the situation in my head, perhaps I could make a table in database with account id and path to file, and use Response::download($pathToFile); And restricting the uploaded files folder with .htaccess no allow?

(Assuming laravels Response::download method bypasses .htaccess) But even if that work it would probably be best to find a way to do this without .htaccess thought?

Edit I guess I will just store the files in the database as blob, and load it from there. That way I can easily do authorisation validation.

user2551614
  • 31
  • 1
  • 1
  • 5

3 Answers3

8

All you have to do is just store files in a private directory (eg. /app/files) and set correct headers.

    $name = 'name.zip';
    $file = '/app/files/name.zip';

    $header = array(
        'Content-Type' => 'application/octet-stream',
        'Content-Disposition' => 'attachment', 
        'Content-length' => filesize($file),
        'filename' => $name,
    );

    // auth code
    return Response::download($file, $name, $header);
vDk3
  • 81
  • 1
  • 3
1

I just came across this and maybe it can help someone too. I used this to "protect" my PDF documents to only logged in users.

I put my files outside the storage/public folder (so non of it was accessable to the public). The Controller was protected by the 'auth' middleware in the constructor.

public function grab_file($hash)
    {
        $file = Publication::where('hash', $hash)->first();

        if ($file) {
            return Response::download(storage_path('app/publications/' . $file->filename), null, [
                'Cache-Control' => 'no-cache, no-store, must-revalidate',
                'Pragma' => 'no-cache',
                'Expires' => '0',
            ], null);
        } else {
            return abort(404);
        }
}

and route is;

Route::get('/user/file/{hash}', 'UserController@grab_file');

Where Publication stored the hash reference to the file. This way there was no way for the user to "see" where the actual file was.

The "no caching" headers made sure the browser didn't cache the PDF. I did that because after logging out, you can still access the file.

Humble Hermit
  • 125
  • 1
  • 8
0

You can restrict the access to download pages using a pattern based filter

Route::filter('download', function()
{
    //here you check if the user is logged in
    if(!Auth::check()){
        return 'you should be logged in to access the download page';
    }
});

Route::when('download/*', 'download'); 

check the documentation for more details

Mohamed Bouallegue
  • 1,334
  • 15
  • 19
  • Yes I know how to restrict pages, but not files, how do I restrict files? So only user can view etc myphoto.png or myarchive.zip? Where the public url link for that particular file is only available for that user? – user2551614 Apr 21 '14 at 13:32
  • ok, I don't know if there is a way to do that with laravel. You can restrict access to file by disabling direct file access in your web server. If you are using apache take a look on this: http://stackoverflow.com/questions/10236717/htaccess-how-to-prevent-a-file-from-direct-url-access – Mohamed Bouallegue Apr 21 '14 at 14:08
  • Masking a file dosn't help much once the link is exposed in regards to security? Perhaps saving and loading files directly from the database as blob is the only way to go then? Sounds a bit scary in regard to SQL performance tho. :/ I also don't want to rely on .htaccess at all so the solution is independent on web server. (etc Lighttpd, nginx). – user2551614 Apr 21 '14 at 14:12