Good Way to Secure File Uploads in PHP

2019-01-17 19:31发布

问题:

Writing a small app that (among other things) lets users upload a file (like an image, a .doc or a text file) as part of their posting/submission.

Our current prototype just dumps the file into /{app_root}/files/, but of course, anyone can get to that even if they are not logged in or using the system. The goal is to only grant access (view access) to the files if user is logged in and does in fact have access to the post that the file belongs to.

So, in short, I am looking for a good way to do this.

I am thinking of either creating a folder outside the /web/ (http) folder and then having PHP render it somehow using header() commans, or, maybe just dumping the file into the database? I have never done either one, however.

While I suspect I can figure it out eventually, there are just too many smart people on here that I was figuring someone will know of some sort of existing class or function library that does this already?

回答1:

You have to do the following:

  1. Move all the files out of the webroot. You could disable access to the folder with .htaccess, but it is not worth the hassle and potential security risk. Just move it out there.
  2. Keep a table of the files uploaded, storing the user's original file name there. Rename the file to $id.$ext and so on. In short, you don't want to use the user's file name in your system.
  3. Have a script, download.php or whatever, get the file's ID, verify who is logged in, and if everything checks out, fetch the file, read it out to the browser, and send the appropriate download headers.

These headers would be something like:

header('Content-type: application/octet-stream');
header('Content-disposition: attachment; filename=usersuppliedname.txt');
header("Content-Length: " . filesize('../safefiles/1.txt'));
header("Content-Transfer-Encoding:  binary");
readfile('../safefiles/1.txt');
exit;

You can then get more fancy if you want to allow resuming files and such, but the above should do it.