URL 拒绝从网络服务器直接下载文件
Deny direct file download from webserver by URL
我有一个用户可以登录的网站,由 sessions 和 $user[id]
识别。他们可以上传文件。文件存储在 htdocs/uploads 中。每个文件数据都存储在 table 中,文件名、位置和 user_id 之间有一个 link。在我网站的某些地方,我提供了通过以下方式下载文件的可能性:<a href="' . $row['path'] . '" target="_blank" download>Download file</a>
.
在$row['path']
后面给出了一个URL如domain.com/uploads/filename.jpg。如果用户知道此 URL 路径,他也可以通过在浏览器中输入 URL 来下载文件,而无需登录或身份验证。我想避免这种情况。我如何确保只能通过单击我网站上的此类下载 link 从 htdocs/uploads 下载文件。
=> 我无法在 htdocs 之外创建文件夹
=> 我已尝试更改文件夹权限,但 w/o 成功
=> 我的网站基本上是用PHP制作的,最好是PHP的解决方案。
有 idea/help 可用的吗?谢谢!
您需要按照 PHP 为您提供文件的路线。这将确保您可以在提供文件之前验证用户凭据。
参见 php.net 上的示例 here. This will explain how to serve files from PHP using header()
. This answer 还概述了一些关键概念。
完成此操作后,您可以使用 htaccess rules 拒绝对这些文件的直接访问。这将确保用户只能通过 php 端点访问文件,并且这些端点可以执行用户凭据的验证。
我已经通过以下操作解决了这个问题:
- 在我的文件夹 htdocs/uploads 中添加了一个 .htaccess 文件,内容如下:
<FilesMatch ".*">
Order Allow,Deny
Deny from All
</FilesMatch>
- 创建了一个文件:file_download.php,内容如下:
// Doing here some user verification based on the session and user_id
if($user['id'] != 'something i want to be') {
die('Not allowed to download this file');
} else {
// Verify the download as requested
// Basic file name
$file = basename($_GET['file']);
// Path where the file should be stored
$file = 'uploads/'.$file;
if(!file_exists($file)){ // file does not exist
die(''.$file.' file not found');
} else {
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$file");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
// read the file from disk
readfile($file);
}
}
- 已将下载 link 从
<a href="' . $row['path'] . '" target="_blank" download>Download file</a>
更改为 <a href="file_download.php?file=<?= $row['path'] ?>Download</a>
这种方式会阻止任何通过在浏览器中使用清除 URL 下载文件的尝试。该文件只能通过具有用户身份和提供的link从我的网站下载。如果有人不需要用户验证,只需删除file_download.php
中的第一个if/else
。
我有一个用户可以登录的网站,由 sessions 和 $user[id]
识别。他们可以上传文件。文件存储在 htdocs/uploads 中。每个文件数据都存储在 table 中,文件名、位置和 user_id 之间有一个 link。在我网站的某些地方,我提供了通过以下方式下载文件的可能性:<a href="' . $row['path'] . '" target="_blank" download>Download file</a>
.
在$row['path']
后面给出了一个URL如domain.com/uploads/filename.jpg。如果用户知道此 URL 路径,他也可以通过在浏览器中输入 URL 来下载文件,而无需登录或身份验证。我想避免这种情况。我如何确保只能通过单击我网站上的此类下载 link 从 htdocs/uploads 下载文件。
=> 我无法在 htdocs 之外创建文件夹
=> 我已尝试更改文件夹权限,但 w/o 成功
=> 我的网站基本上是用PHP制作的,最好是PHP的解决方案。
有 idea/help 可用的吗?谢谢!
您需要按照 PHP 为您提供文件的路线。这将确保您可以在提供文件之前验证用户凭据。
参见 php.net 上的示例 here. This will explain how to serve files from PHP using header()
. This answer 还概述了一些关键概念。
完成此操作后,您可以使用 htaccess rules 拒绝对这些文件的直接访问。这将确保用户只能通过 php 端点访问文件,并且这些端点可以执行用户凭据的验证。
我已经通过以下操作解决了这个问题:
- 在我的文件夹 htdocs/uploads 中添加了一个 .htaccess 文件,内容如下:
<FilesMatch ".*">
Order Allow,Deny
Deny from All
</FilesMatch>
- 创建了一个文件:file_download.php,内容如下:
// Doing here some user verification based on the session and user_id
if($user['id'] != 'something i want to be') {
die('Not allowed to download this file');
} else {
// Verify the download as requested
// Basic file name
$file = basename($_GET['file']);
// Path where the file should be stored
$file = 'uploads/'.$file;
if(!file_exists($file)){ // file does not exist
die(''.$file.' file not found');
} else {
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$file");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
// read the file from disk
readfile($file);
}
}
- 已将下载 link 从
<a href="' . $row['path'] . '" target="_blank" download>Download file</a>
更改为<a href="file_download.php?file=<?= $row['path'] ?>Download</a>
这种方式会阻止任何通过在浏览器中使用清除 URL 下载文件的尝试。该文件只能通过具有用户身份和提供的link从我的网站下载。如果有人不需要用户验证,只需删除file_download.php
中的第一个if/else
。