限制文件访问 - 仅通过PHP读取

时间:2010-08-12 23:21:00

标签: php pdf iis restrict

我在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 个答案:

答案 0 :(得分:7)

既然你不能把文件放在你的public_html目录中的任何地方,你就必须采取令人畏惧/讨厌的“默默无闻”的方法

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

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

  3. 请勿使用可猜测的名称存储文件。不是将它们与数据库ID一起存储,而是使用salted + hashed名称存储它们:$crypted_filename = sha1($real_filename . 'some hard-to-guess salt text');(当然,如果需要,可以使它更复杂)。将原始文件名存储在数据库中。所以你最终得到的结果是:

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

  4. 通过PHP脚本提供文件 - 永远不要直接链接到哈希文件名

    下载

  5. 然后:

    <?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值更新所有散列文件名)。 / p>

答案 1 :(得分:1)

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

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

asd8b8asd8327bh/123.pdf
asd8b8asd8327bh/124.pdf
asd8b8asd8327bh/125.pdf
...

然后给自己写一个小脚本,发送适当的标题,并传递文件内容。

例如:

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

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

答案 2 :(得分:1)

由于PHP使用Web服务器用户的权限,因此没有办法限制对文件的访问:

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

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

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

答案 3 :(得分:0)

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

实施例: 这设置为770,IE用户和组可以读/写/执行,其他无法执行任何操作。