1

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

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

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

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

4

2 回答 2

5

从问题和评论来看,您似乎在寻找看起来像直接访问的 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的修改版本。我只在此处发布相关部分(可以在 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;

至此,这个关于如何获取有效下载脚本并使其看起来像直接文件访问的小示例结束。

于 2013-04-14T23:24:09.500 回答
2

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

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

  • 提供 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);
    
于 2013-04-14T23:27:23.373 回答