如何在服务器上安全地存储文件

Posted

技术标签:

【中文标题】如何在服务器上安全地存储文件【英文标题】:How to securely store files on a server 【发布时间】:2012-05-18 18:56:53 【问题描述】:

我在做什么:

我基本上需要创建一个由用 php 编写的登录页面保护的网站,一旦登录,您就会有一个读取整数的搜索栏,并且数据被发送到一个 PHP 脚本,该脚本检索一个以数字为名称的图像.

(我将在此服务器上存储几千张图片以供搜索 - 库存图片)

-

我需要什么帮助:

根据我的研究,我了解到您“不”使用 mysql 等数据库来存储实际图像,因为速度和效率低下。如果您不将其存储在数据库中,而是按照建议将其保留在服务器的文件系统中,如果有人在地址栏中键入直接 URL,它不会将它们带到我服务器上的文件中吗?

您如何防止这种情况发生。如果没有成功通过登录页面,我不希望服务器上的任何文件都可以查看。

感谢您的帮助,任何见解或建议将不胜感激。这对我来说很重要,因为将来会添加更复杂的信息。

【问题讨论】:

您可以拥有一个无法通过 HTTP 访问的目录,您可以使用 php 脚本检查用户是否已登录,如果是,则从指定目录读取文件并输出。 我已经阅读了将文件保留在“public_html”文件夹之外的内容。这会使它完全无法从http访问吗?那么我的 php 脚本如何访问这些文件呢? public_html 通常是使用 Apache 和 cPanel 时提供文件的目录。这意味着当您键入http://yoursite.com 时,数据将从/var/www/username/public_html 中提取。这也意味着无论您在 URL 中键入什么,/var/www/username不可访问。这也意味着您在此处创建的目录(例如 /var/www/username/files)也将无法访问。在您的 PHP 脚本中,您可以使用 file_get_contents('/var/www/username/files/imagename.extension);` 之类的方式访问它。 php 可以访问服务器上的任何文件(取决于权限)它不受网络根目录的限制 好的,谢谢你们,现在我知道如何存储我的文件了。我应该使用数据库来存储文件路径,还是应该完全忽略数据库?对路径进行硬编码,并为输入(图像的名称)提供一个变量保存位置? 【参考方案1】:

通过 PHP(或任何其他脚本)处理文件下载的推荐方法是使用所谓的“X-Sendfile”响应标头。

PHP 脚本处理身份验证,一旦验证,它将设置一些响应标头和一个“X-Sendfile”,告诉 Web 服务器发送文件;脚本结束,网络服务器接管。

这里有一个简单的例子:

http://www.jasny.net/articles/how-i-php-x-sendfile/

【讨论】:

【参考方案2】:

这对于您的情况来说可能有点矫枉过正,但这就是我正在考虑在我正在开发的应用程序上执行此操作的方式:

首先,有4台服务器,一个web服务器,一个中间件服务器,一个数据服务器

当有人向 Web 服务器发送请求时,Web 服务器会连接到中间件服务器并请求文件,并传递用户凭据(如会话密钥)和请求的文件。中间件连接到数据库并验证会话和用户对该文件的权限。如果他们有权访问,它将返回错误或二进制数据。如果你在 web 服务器和中间件服务器上都关闭了输出缓冲,你可以从中间件服务器发送 100k 块到 web 服务器,web 服务器将在接收第二块时输出第一个块。

文件本身可以通过 ftp、sftp 或其他文件共享方式存储在数据库服务器上

它肯定不如使用 x-sendfile 高效,但是如果有人能够 pwn 您的 Web 服务器,他们仍然无法访问该文件 - 在上述情况下,他们会。 Web 服务器是唯一的公共服务器,因此其余服务器应连接到专用网络。

您还可以将数据发送到将加密/解密实际文件数据的加密服务器

如果有人对如何改进这一点有任何想法,我很感兴趣。

【讨论】:

很有趣,但这肯定比我需要的复杂(但读起来很有趣)。老实说,当时我不知道 .htaccess 并且它可以阻止查看整个文件夹。我已经实现了这一点。我有一个 HTML 登录表单,它获取数据,将其发送到验证用户的处理脚本,如果验证,则将用户发送到搜索页面。用户输入一个 Item # 并被发送到另一个处理脚本,该脚本以数字作为主键访问数据库,保存文件路径和其他信息。如果存在,则拉取文件路径 图像文件夹受 .htaccess ("DENY FROM ALL") 保护。我还使用 SSL 并将有关图像的其他信息存储在 MySQL 数据库中【参考方案3】:

你可以这样做 像这样在php中编写资源服务

image.php?requestid=.....

在该文件中,您获取 requestid 并从数据库中读取实际链接(本地链接),读取图像文件然后将数据输出到浏览器

$id = $_GET['requestid'];
$link = get_local_link_from_id($id);  // return /images/file1.png......
$data = file_get_contents($link);
header('Content-Type', 'image/png');
echo $data;

但我认为你不应该这样做,只是随机重命名文件并创建很多......

【讨论】:

他们需要保留原始号码,这不是我的系统,而是雇用我的人要求的。这足够安全吗?只要我的 PHP 脚本过滤请求,对吗? GET 从来都不是安全的,即使是 POST 也可能不足以保证安全。 @ilis - 你的评论有什么意义? GET 和 POST 是 HTTP 使用的方法,只有在解释用户输入时被误用,它们才是“不安全的”。 @N.B.我想我暂时还不足以解释他们不安全的观点。但我会在短时间内返回这里并提供完整的详细信息(几天后) 有什么好讨论的?使用 HTTP 传递数据的唯一方法是使用 GET/POST(在当前上下文中)。你说他们没有安全感。不,他们不是不安全的。不安全的是您如何解释该数据,就像其他任何协议一样。协议或上述两种方法都没有问题。请不要发布误导性的 cmets。

以上是关于如何在服务器上安全地存储文件的主要内容,如果未能解决你的问题,请参考以下文章

如何安全地存储加密密钥?

安全地存储数据

在 Android 密钥库中安全地存储密钥

如何安全地存储和使用客户的 AWS 密钥

如何安全地存储 Discord(OAuth2) 用户的访问令牌?

我应该如何安全地存储密码并在 chrome 扩展中使用 http auth