10

我在 Windows 平台上使用 GoDaddy 网络托管计划。这不是我的选择——它与使用 ASP.NET 的实际站点的不同部分有关(也不是我的选择)。

我有一个 SQL 数据库,其中包含一些非敏感客户信息的条目。这方面的主键是一个 AutoIncrement 整数,我有一系列与每个整数匹配的 PDF 文件(例如 555.pdf、7891.pdf 等)。

我的目标是限制对这些文件的直接访问,我希望用户必须首先通过搜索和登录过程 (PHP)。最初我计划将文件放在 PUBLIC_HTML 文件夹上方,但 GoDaddy 拒绝在没有专用服务器的情况下为我提供 root 访问权限(他们每月 20 美元)。

接下来我研究的是 HTACCESS。我打算通过只允许访问服务器的 IP 地址(或 localhost/127.0.0.1)来限制对文件的访问,仅限 PHP 脚本。不幸的是,这不起作用,因为 GoDaddy 不在其 Windows 服务器上运行 Apache。

我可以将文件放入数据库中的 BLOB 中,但是当我需要快速使用它们时会变得非常混乱(而且我在使用这种方法时遇到了一些问题)。

有什么建议可以限制对文件的访问仅限于 PHP 脚本 (readfile())?

4

4 回答 4

7

由于您不能将文件放在 public_html 目录中的任何位置,因此您必须采用令人恐惧/讨厌的“默默无闻的安全性”方法

  1. 创建一个随机命名的子目录来存储文件:public_html/RANDOMGARBAGE

  2. 确保目录不可浏览。禁用目录浏览(如果可以的话),并在其中放置一个默认文档(index.html?),因此即使打开浏览,您也不会获得目录列表。

  3. 不要使用可猜测的名称存储文件。与其将它们与数据库 ID 一起存储,不如将它们存储为一个加盐+散列的名称:($crypted_filename = sha1($real_filename . 'some hard-to-guess salt text');当然,如果需要,可以使这更复杂)。将原始文件名存储在数据库中。所以你最终会得到类似的东西:

    public_html/RANDOMGARBAGE/5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 public_html/RANDOMGARBAGE/7ec1f0eb9119d48eb6a3176ca47380c6496304c8

  4. 通过 PHP 脚本提供文件 - 切勿直接链接到散列文件名

    下载

然后这样做:

<?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

最重要的是,您偶尔可以定期将特殊子目录重命名为其他内容,以及更改 salt 文本(这需要您使用新的 sha1 值更新所有散列文件名)。

于 2010-08-13T00:07:58.837 回答
1

您可以简单地隐藏它们。它是通过默默无闻的安全性,但如果您不能将它们排除在 Web 根目录之外,或者找到一种方法告诉服务器不要直接为它们提供服务,这听起来像是您的最佳选择。

所以把它们放在一些随机命名的目录中:

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 参数。

但是你应该能够很容易地弄清楚如何处理授权。

于 2010-08-12T23:28:19.567 回答
1

因为 PHP 使用 Web 服务器用户的权限,所以如果没有以下任何一项,就无法限制对文件的访问:

  • 将它们放在 DOCROOT 之外
  • 更改 Web 服务器配置以禁止访问这些文件
  • 更改文件以使其被 Web 服务器解释,从而隐藏其内容

将它们放入数据库算作 DOCROOT 之外。对于第三个选项,您可以制作 PDF 的 PHP 文件,但老实说,这将是相当复杂的。

我建议您联系 GoDaddy,看看他们是否有办法配置每个目录的文件权限。

于 2010-08-12T23:30:37.580 回答
0

通过 chmod 使文件夹 web 无法访问。PHP 仍然能够包含/要求服务器上的任何内容,但用户将永远无法导航到文件。

例子:这个设置为770,IE用户和组可以读/写/执行,其他什么都不做。

于 2010-08-12T23:28:44.603 回答