限制文件访问——只能通过 PHP 读取
我在 Windows 平台上使用 GoDaddy 网络托管计划.这不是我的选择——它与使用 ASP.NET 的实际站点的不同部分有关(也不是我的选择).
I am using a GoDaddy web hosting plan on a Windows platform. This was not my choice -- it has to do with a different part of the actual site using ASP.NET (also not my choice).
我有一个 SQL 数据库,其中包含一堆包含一些非敏感客户信息的条目.主键是一个 AutoIncrement 整数,我有一系列与这些整数匹配的 PDF 文件(例如 555.pdf、7891.pdf 等).
I have a SQL database with a bunch of entries with some non-sensitive customer information. The primary key on this is an AutoIncrement integer, and I have a series of PDF files that match up with each of those integers (e.g. 555.pdf, 7891.pdf, etc).
我的目标是限制对这些文件的直接访问,我希望用户必须首先通过搜索和登录过程 (PHP).最初我计划将文件放在 PUBLIC_HTML 文件夹上方,但 GoDaddy 拒绝在没有专用服务器的情况下授予我 root 访问权限(他们每月 20 美元).
My goal is to restrict direct access to these files, I want users to have to go through a search and login process (PHP) first. Originally I planned to put the files above the PUBLIC_HTML folder, but GoDaddy refuses to give me root access without a dedicated server ($20 a month from them).
接下来我研究的是 HTACCESS.我打算通过只允许访问服务器的 IP 地址(或 localhost/127.0.0.1)来将文件的访问限制为仅 PHP 脚本.不幸的是,这不起作用,因为 GoDaddy 不在其 Windows 服务器上运行 Apache.
The next thing I looked into was HTACCESS. I was going to restrict access to the files to only PHP scripts by only allowing access to the Server's IP Address (or localhost/127.0.0.1). Unfortunately this doesn't work because GoDaddy does not run Apache on its Windows servers.
我可以将文件放入数据库中的 BLOB 中,但是当我需要快速处理它们时,这会变得非常混乱(而且我在使用这种方法时遇到了一些问题).
I could put the files into BLOBs in the database, but that gets really messy when I need to work with them quickly (plus I have had some trouble with that approach).
是否有任何建议将文件的访问权限限制为 PHP 脚本(readfile())?
Any suggestions to restrict access to the files only to a PHP script (readfile())?
推荐答案
由于您不能将文件放在 public_html 目录之外的任何位置,因此您将不得不采用令人恐惧/讨厌的隐匿安全"方法
Since you can't put the files anywhere but in your public_html directory, you'll have to go for the feared/hated "security by obscurity" method
创建一个随机命名的子目录来存储文件:public_html/RANDOMGARBAGE
Create a randomly named sub-directory to store the files in: public_html/RANDOMGARBAGE
确保目录不可浏览.禁用目录浏览(如果可以),并在其中放置一个默认文档(index.html?),这样即使打开浏览,您也不会获得目录列表.
Make sure the directory is not browseable. Disable directory browsing (if you can), and put a default document (index.html?) in there as well, so even if browsing is on, you won't get the directory listing.
不要使用可猜测的名称存储文件.不是将它们与数据库 ID 一起存储,而是使用加盐+散列名称存储它们: $crypted_filename = sha1($real_filename . 'some hard-to-guess salt text');
(当然,如果需要,请使其更复杂).将原始文件名存储在您的数据库中.所以你最终会得到类似的东西:
Don't store your files with guessable names. Instead of storing them with the database ID, store them with a salted+hashed name instead: $crypted_filename = sha1($real_filename . 'some hard-to-guess salt text');
(of course, make this more complex if you need to). Store the original filename in your database. So you end up with something like:
public_html/RANDOMGARBAGE/5bf1fd927dfb8679496a2e6cf00cbe50c1c87145
public_html/RANDOMGARBAGE/7ec1f0eb9119d48eb6a3176ca47380c6496304c8
通过 PHP 脚本提供文件 - 不要直接链接到散列文件名
Serve up the files via a PHP script - never link to the hashed filename directly
下载
然后这样做:
<?php
$fileID = (int)$_GET['fileID'];
$crypted_file = sha1($fileID . 'some hard-to-guess salt text');
$full_path = 'public_html/RANDOMGARBAGE/' . $crypted_file;
if (is_readable($full_path)) {
if(user_is_allowed_to_see_this_file()) {
/// send file to user with readfile()
header("Content-disposition: attachment; filename=$ORIGINAL_FILENAME");
readfile($full_path);
} else {
die("Permission denied");
}
} else {
/// handle problems here
die("Uh-oh. Can't find/read file");
}
这样用户将永远不会看到您的s00per seekrit"文件名是什么,他们只会看到他们的浏览器点击了...php?fileID=37
并开始下载秘密文件.pdf
This way the user will never see what your "s00per seekrit" filename is, they'll just see their browser hit ...php?fileID=37
and start a download of secret file.pdf
最重要的是,您可以偶尔定期将特殊子目录重命名为其他名称,以及更改盐文本(然后需要您使用新的 sha1 值更新所有散列文件名).
On top of this, you can occasionally rename the special sub-directory to something else on a regular basis, as well as change the salt text (which then requires you update all the hashed filenames with the new sha1 values).
相关文章