【问题标题】:protect files via .htaccess and PHP通过 .htaccess 和 PHP 保护文件
【发布时间】:2026-02-03 21:30:01
【问题描述】:

之前可能已经讨论过,但我就是找不到快速干净的解决方案。

1) 我的/data/ 文件夹中有一堆文件:.jpg、.gif、.mp4、.pdf 等。

2) 我想创建一个/data/.htaccess 文件,它将捕获每个请求并将其重定向到 PHP 处理器,例如:

/data/filename.jpg -> /data/processor.php?file=filename.jpg

3) processor.php 将执行以下操作:

3a) 检查您是否有有效的$_SESSION['logged_in'] == TRUE

3b) 发送相应的标头

3c) 发送文件数据

理想情况下,.htaccess 重定向不会更改浏览器的 URL,因此只要您登录,所有当前文件请求都将保持有效。

编辑:

正如建议的那样,更好的方法是将我的文件保存在 Web 根目录之外。因此,我将只保留/html/data/processor.php 并将所有媒体文件(如 .jpg 和 .mp4)移动到 Web 根目录之外的 /media/

【问题讨论】:

  • 你最好不要把这样的文件放在网络根目录之外。文件将无法直接下载,php可以访问文件没有问题。然后只需将一个与文件对应的 id 传递给 php 或使用 htaccess 并将路径下的所有请求重定向到 php 并解析路径以获取文件名。
  • 同意将文件保存在 Web 根目录之外!好点+1

标签: php .htaccess redirect http-headers


【解决方案1】:

如果您不想在浏览器中更改 URL,那么您需要的是 URL 重写而不是重定向。您的 .htaccess 文件应如下所示:

RewriteEngine On
RewriteRule ^data/(.+) /data/processor.php?file=$1 [L]

这将导致对/data/filename.jpg 的请求实际请求/data/processor.php?file=filename.jpg,而不对浏览器中的URL 做任何事情。然后您的 processor.php 脚本可以从那里接管。

请记住,您必须在服务器配置中启用 mod_rewrite。

还有其他需要考虑的。您可能希望也可能不希望将这些文件保留在文档根目录之外,具体取决于哪个更重要:安全性或可用性。如果 ,htaccess 部分由于某种原因失败,您是否希望文件默认可访问?换句话说,在这种情况下,您是否让用户怀疑他们的访问权限?如果是这样,最好将文件留在原处,因为 URL 将正常工作并交付用户期望的文件。如果您想在不授予访问权限方面出错,那么将文件移到文档根目录之外会很好,这样如果没有通过您的脚本的 mod_rewrite 规则就无法访问它们。

/data/processor.php

以下是您的处理器的样例:

<?php
// Get MIME Type
    $finfo     = finfo_open( FILEINFO_MIME_TYPE );
    $mime_type = finfo_file( $finfo, $_GET['file'] );
    finfo_close( $finfo );

// Send headers
    header( "Content-Type: $mime_type" );
    header( "Content-Length: " . filesize( $_GET['file'] );

// Send file data
    readfile( $_GET['file'] );
?>

如有必要,请务必包含路径以及 $_GET['file'],具体取决于您最终找到文件的位置。

【讨论】:

  • 是否有我应该使用的已知 PHP 脚本?就像检查 Session 变量没什么大不了的,但是将每个扩展名与适当的标题匹配,然后输出文件内容。我该怎么做?
  • @Geo 如果您查看 header 的 php 手册页,在用户 cmets 中有一些应该可以正常工作的示例。类似this
  • @Geo:我建议遵循@Jonathan Kuhn 提到的脚本,但有一个小例外。我建议不要尝试将扩展名与 mime 类型匹配,而是查看 FileInfo 函数:php.net/manual/en/ref.fileinfo.php
  • 我会很感激答案中的实际代码,所以我可以接受。我很清楚header 部分。输出文件内容呢?
  • 我已经用一些示例代码更新了答案以帮助您入门。
【解决方案2】:

这是为我解决的完整解决方案。以防万一它可能对任何人有用。谢谢@Nick Coons!

HTAccess 文件/html/media/.htaccess

RewriteEngine On

RewriteCond %{REQUEST_URI} \.(png|jpe?g)$ [NC]
RewriteRule ^(.+) index.php?file=$1 [L]

处理器文件/html/media/index.php

<?php

require_once '../config/config.php';

// must be logged in
if ( ! @$_SESSION['logged_in']) exit('Access denied. You are not logged in.');

// check if file exists
$file = dirname(dirname(getcwd())) . '/media/' . @$_GET['file'];
if ( ! is_file($file)) exit('404');

// Get MIME Type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $file);
finfo_close($finfo);

// Send headers
header("Content-Type: $mime_type");
header('Content-Length: ' . filesize($file));

// Send file data
readfile($file);

/* End of file */

媒体文件夹/media/

.png and .jpg files are stored here outside of the web-root

现在对/html/media/bike.png 的请求仅适用于登录用户。

【讨论】: