题
我正在Windows平台上使用Godaddy的网络托管计划。这不是我的选择 - 它与使用ASP.NET的实际站点的不同部分有关(也不是我的选择)。
我有一个SQL数据库,其中包含许多条目,其中包含一些不敏感的客户信息。这是一个自动启动整数,我有一系列与每个整数匹配的PDF文件(例如555.pdf,7891.pdf等)。
我的目标是限制对这些文件的直接访问,我希望用户必须先进行搜索和登录过程(PHP)。最初,我计划将文件放在public_html文件夹上方,但Godaddy拒绝在没有专用服务器的情况下给我root访问(每月20美元)。
我关注的下一件事是htaccess。我将仅允许访问服务器的IP地址(或localhost/127.0.0.1),将对文件的访问限制在PHP脚本中。不幸的是,这无效,因为Godaddy不会在其窗户服务器上运行Apache。
我可以将文件放入数据库中的斑点,但是当我需要快速与它们合作时,这真的会变得凌乱(此外,我在这种方法上也遇到了一些麻烦)。
有任何建议只限制对文件访问仅到PHP脚本(ReadFile())的建议?
解决方案
由于您不能将文件放在任何地方,但是在您的public_html目录中,您必须选择恐惧/讨厌的“安全性”方法
创建一个随机命名的子目录以存储文件中的文件:public_html/RandomGarbage
确保目录不可浏览。禁用目录浏览(如果可以的话),并将默认文档(index.html?)放入其中,因此,即使浏览已打开,您也不会获得目录列表。
不要将您的文件存储使用可猜测的名称。而不是使用数据库ID存储它们,而是用咸+哈希名称存储:
$crypted_filename = sha1($real_filename . 'some hard-to-guess salt text');
(当然,如果需要的话,使它更加复杂)。将原始文件名存储在数据库中。因此,您最终得到了类似的事情:public_html/RANDOMGARBAGE/5bf1fd927dfb8679496a2e6cf00cbe50c1c87145
public_html/RANDOMGARBAGE/7ec1f0eb9119d48eb6a3176ca47380c6496304c8
通过php脚本将文件发送 - 切勿直接链接到Hashed FileName
下载
然后这样做:
<?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
然后开始下载 secret file.pdf
最重要的是,您偶尔可以定期将特殊子目录重命名为其他内容,并更改盐文本(然后要求您更新所有带有新的SHA1值的Hashed文件名)。
其他提示
您可以简单地隐藏它们。这是安全性的,但是如果您不能将它们放在网上,或者找到一种方法来告诉服务器不要直接服务它们,则听起来像是您的最佳选择。
因此,将它们粘在一些随机命名的目录中:
asd8b8asd8327bh/123.pdf
asd8b8asd8327bh/124.pdf
asd8b8asd8327bh/125.pdf
...
然后写下一些PHP脚本,该脚本将发送适当的标题,然后传递文件内容。
例如:
<?PHP
//pdf.php
$id = $_GET['id'];
//make sure nobody is doing anything sneaky. is_numeric() might do the trick if the IDs are always integers.
if (!some_validation_passes($id)){
die();
}
<?php
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="'.$id.'.pdf"');
readfile('asd8b8asd8327bh'.$id.'pdf');
现在,以上实际上并不比直接服务文件(目前)更好,因为人们仍然可以在查询字符串中递增ID参数。
但是您应该能够弄清楚如何轻松处理授权。
由于PHP使用Web服务器用户的权限,因此无需任一任务即可限制对文件的访问:
- 将它们放在Docroot外面
- 更改Web服务器配置以禁止访问这些文件
- 更改文件,以便由Web服务器解释,从而隐藏其内容
将它们放入数据库中是在DocRoot之外的。对于第三个选项,您可以制作PDFS PHP文件,但老实说,这将非常令人费解。
我建议您联系Godaddy,看看他们是否有某种方式配置人均文件权限。
通过CHMOD制作一个无法访问的文件夹。 PHP仍然可以包括/需要服务器上的任何内容,但是用户将无法导航到该文件。
示例:将其设置为770,IE用户和组可以读/写/执行,其他人无能为力。