如何保护我的 NGiNX 服务器上的文件?

如何保护我的 NGiNX 服务器上的文件?

我正在尝试使用 NGiNX 和 PHP 保护我的服务器上的文件(多种类型)。

基本上,我希望人们在访问静态文件(如图片)时必须登录网站。DropBox 在这方面做得很好。而他们却强迫你登录才能访问你放在服务器上的任何静态文件。

我考虑使用 NGiNX Perl 模块。我会编写一个 perl 脚本来检查会话,看看用户是否已登录,以便让他们访问静态文件。

我更喜欢使用 PHP,因为我的所有代码都在 PHP 下运行,而且我不确定如何使用 PERL 检查由 PHP 创建的会话。

所以基本上我的问题是:如何保护需要用户登录并使用 PHP 脚本创建有效会话的任何类型的静态文件?

答案1

你问的是两件事:

  1. 如何防止外部访问文件(或文件集)
  2. 如何验证用户身份并允许 PHP(和用户)访问文件

希望这可以阐明每个组件所起的作用 - 尽管可能有点过分。

防止外部访问文件:

这部分由您的 Web 服务器完成 - 在本例中为 nginx。

在您的 nginx 配置(您的服务器块)中,您可以指定一个root路径。默认情况下,此根路径下的所有文件都可以直接访问。

例如,考虑以下内容(域名为“example.com”)

root /var/www/example.com/public_html

如果您有一个文件,uploaded_file.zip则可以通过以下方式访问:

  • 位置:/var/www/example.com/public_html/uploaded_file.zip -无障碍通过 example.com/uploaded_file.zip
  • 位置:/var/www/example.com/uploaded_file.zip -无法访问(即使使用 example.com/../uploaded_file.zip)

本质上,文档根目录上方的文件无法通过浏览器访问,但是,大多数 PHP 配置将允许您的代码读取文件并传送它(对此的限制通常是由于open_basedir

在某些情况下,最好将文件放在文档根目录下。要做到这一点并防止(直接)外部访问,您将使用指令internal。例如:

位置 /uploads { 内部; }

现在,放置在 /var/www/example.com/public_html/uploads 中的任何文件都只能在内部访问(即无法通过浏览器访问,但可以通过 PHP 脚本访问)。如果需要,您还可以在 /uploads 位置上设置别名,以便也可以使用其他路径来引用它。

此时,您的文件不能直接访问,但您的脚本仍然可以为其提供服务。

用户身份验证和 PHP:

考虑以下基本设计:用户可以直接访问文件,也可以进入登录页面。如果他们尝试直接访问文件并且已登录(并具有权限),则将下载该文件,否则,他们将最终进入登录屏幕。要上传文件,用户需要登录。

假设您的下载脚本(将文件传递给用户的页面)名为“download.php”。典型的 URL 可能是 example.com/download.php?file=uploaded_file.zip。您很可能不希望 URL 包含 php 文件名。为了避免这种情况,您可以在 nginx 配置中设置重写规则,将另一个位置(假设为 /files)指向您的脚本。将以下内容添加到您的 nginx 配置中:

rewrite ^/files/(.*) /download.php?file=$1 last;

(这相当于改变以 /files 开头的任何请求的请求路径,并捕获 / 之后的所有内容并将其作为查询参数传递给您的 php 文件);

现在,您可以通过以下方式访问您的文件:example.com/files/uploaded_file.zip(内部重定向到您的 php 脚本)。

您的 PHP 文件 (download.php) 现在执行以下操作:

  • 开始会话
  • 如果用户已登录,则继续,否则,重定向到登录页面,并将目标文件作为查询字符串的一部分传递
  • 查询你的数据库(例如 MySQL)以查看用户是否可以访问此文件
    • 如果用户有权限,则继续,否则,重定向到错误页面
  • 输出必要的标题(Content-Type,Content-Disposition等)并设置:

    X-Accel-Redirect: /uploads/uploaded_file.zip;

请注意,您可以完全通过 PHP 进行实际下载(例如使用readfile)——它只是效率更高一点,尤其是对于大文件而言)而不是通过 nginx 进行下载。此外,尽管用户似乎直接访问文件,但在内部,它要经过 PHP 的验证,PHP 会在允许他们继续之前对其进行身份验证。

URL -> nginx (redirect to PHP) -> PHP (authenticate) -> nginx (serve file)

在上传方面,您将move_uploaded_file访问 /var/www/example.com/public_html/uploads(受“internal”指令保护,因此文件不能直接访问),并将权限保存到您的数据库。

相关内容