【问题标题】:How to prevent non members from directly accessing private content with PHPPHP如何防止非会员直接访问私有内容
【发布时间】:2013-04-14 22:04:56
【问题描述】:

我知道 .htaccess Apache 保护文件夹免受非成员访问的方法,但我想知道如何仅使用 PHP 来完成。

检查会话变量可以保护 php 页面,但直接访问照片和或 pdf 似乎有时会被忽略。例如,如果我从 facebook 复制照片的直接链接,注销,然后将我的浏览器定向到照片的 url,它显示没有问题。

Rapidshare 等网站如何防止对其内容的直接访问?

我知道有一种方法可以在 Apache 中设置变量。也许有办法用 Apache 检查会话变量?

【问题讨论】:

  • 如果它位于网络可访问区域,PHP 无法保护它
  • 在内容文件夹中,您可以deny from all,然后使用 php 脚本打开文件并将其直接输出到浏览器,以便允许的用户访问它们。 (我相信那些网站会重写脚本以使其看起来像直接访问)
  • @Jon - 但这不是他们正在寻找的 PHP 方法
  • Rapidshare 等不提供对其内容的直接访问。他们使用下载脚本。
  • @JohnConde 是的,但如果将.htaccess 中看起来像direct access 的内容重写为PHP 脚本,并将内容存储在拒绝访问的目录中,这将是解决方案的类型他正在寻找(我相信)。 ^^

标签: php apache security password-protection


【解决方案1】:

从问题和 cmets 看来,您似乎在寻找看起来像直接访问的 URL,但通过 PHP 脚本允许授权下载它们。我不知道你当前的目录结构,所以我要为这个答案的测试用例补一个——尽管是一个小清单:

public-html/
    content/        <- where the actual files are
        .htaccess   <- to deny access to the directory
    .htaccess       <- the one created here
    download.php    <- download script

据此,我们将假设所有文件都位于/content 中,“直接链接”看起来会指向/file

/content/.htaccess:

deny from all

下一个注释是第一个RewriteRule 是为了不覆盖已经存在的普通文件,而前面的.htaccess 防止访问该目录中的文件。如果您有一个已经在使用的.htaccess,则重要的规则是最后一个,如果匹配,它将停止处理,因此请将其相应地放在您现有的.htaccess 中。

/.htaccess:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} -s [OR]
    RewriteCond %{REQUEST_FILENAME} -l [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^.*$ - [NC,L]

    RewriteRule ^file/(.+)$ download.php?file=$1 [L]
</IfModule>

有了这个,如果转到/file/myDocument.pdf,它看起来就像直接访问一个文件,它将被发送到像download.php?file=myDocument.pdf这样的脚本。

从那里开始创建要使用的下载脚本。我发布的是来自Armand Niculescu found here 的一个修改版本。我只在此处发布相关部分(the entirety can be found on PasteBin 您可以修改此处发布的部分以满足您的需要):

/******************************
 * PERFORM AUTHORIZATION HERE *
 *   The following is added   *
 ******************************/
if($_SESSION['validated'] !== true) {
    //Not authorized to download, send header and exit
    header("HTTP/1.0 401 Unauthorized");
    exit;
}

我还对正确的文件路径进行了另一个小编辑,向下 8 行:

$file_path  = './content/' . $file_name;

这就是如何获得一个工作下载脚本并使它看起来像直接文件访问的小例子。

【讨论】:

  • 在您编辑的版本中,您在脚本顶部缺少session_start()
【解决方案2】:

从您的问题中,我了解到您已经知道如何保护文件夹不被直接访问以及如何保护 php 脚本。所以你需要的是一个受保护的 php 脚本,提供对文件的间接访问(正如 cmets 中已经提到的那样)。

在创建此下载脚本时,您应该记住一些重要的细节:

  • 提供 mime 类型。但在许多情况下,header("Content-Type: application/octet-stream") 就足够了
  • 告诉客户端下载文件(而不是显示它)并提供文件名:header('Content-Disposition: attachment; filename="' . basename($path) . '"')
  • 提供文件大小:header("Content-Length: " . filesize($path));
  • 为避免大文件出现问题,您应该使用类似以下的内容而不是 readfile

    $file = fopen($path, 'r');
    flush(); 
      while (!feof($file)) { 
      print(fread($file, 4096)); 
      flush(); 
    }
    fclose($file);
    

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-09-16
  • 1970-01-01
  • 2020-09-21
  • 2012-05-22
  • 2010-11-05
  • 2010-09-16
  • 1970-01-01
  • 2020-09-25
相关资源
最近更新 更多