在 PHP 中保护文件上传的好方法
编写一个小应用程序(除其他外)允许用户上传文件(像图像、.doc 或文本文件)作为他们发布的一部分/提交.
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.
我们当前的原型只是将文件转储到 /{app_root}/files/,当然,任何人都可以访问它,即使他们没有登录或使用系统.目标是仅在用户登录并且确实有权访问文件所属的帖子时才授予对文件的访问权限(查看访问权限).
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.
我正在考虑在 /web/ (http) 文件夹之外创建一个文件夹,然后让 PHP 使用 header()以某种方式呈现它strong> commans,或者,也许只是将文件转储到数据库中?但是,我从来没有做过任何一个.
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?
推荐答案
你必须做到以下几点:
- 将所有文件移出 webroot.您可以使用 .htaccess 禁用对文件夹的访问,但这不值得麻烦和潜在的安全风险.把它移到那里.
- 保留上传文件的表格,将用户的原始文件名存储在那里.将文件重命名为
$id.$ext
等等.简而言之,您不想在系统中使用用户的文件名. - 有一个脚本,
download.php
或其他任何东西,获取文件的 ID,验证谁登录,如果一切顺利,获取文件,将其读出到浏览器,然后发送适当的下载标头.
- 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.
- 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. - 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.
这些标题将类似于:
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.
相关文章