如何安全地将用户文件夹存储在服务器中?

How can I securely store user folders in a server?

我正在使用 PHP(Laravel 框架)开发一个项目。该项目允许登录用户存储只有他们可以访问的文件和文件夹。

我已经设置了用户身份验证,因此需要唯一的用户令牌才能访问用户数据。 当用户stores/creates一个文件夹时,该文件夹被存储在服务器上,前面加上一个随机的32个字符串复杂的路径,例如/WijiIHSIUhoij99U8EJIOJI09DJOIJob/username/folder,它存储在一个MySQL 数据库供用户使用 API 获取,只要他们的帐户具有正确的访问令牌。我这样做是因为我猜它看起来更安全,如果我错了请纠正我。

这是工作的一半(如果我到目前为止所做的是错误的或不好的做法,请纠正我)。 我现在需要的是确保没有人可以访问根文件夹 / 并获取用户文件夹列表。 但我担心如果我限制对根文件夹的访问,用户将无法再访问他们的文件夹。

我什至不知道从哪里开始寻找解决方案,所以任何事情,即使只是为了让我开始,都会有所帮助。

随机字符串是多余的,因为您的令牌会为您进行随机化。如果用户知道他们的东西存储在 /RANDOMSTRING/folder 中,无论如何都会有人构建一个机器人来尝试所有这些,但我认为这个想法接近你想要的。

相反,尝试创建一个捕获所有 404 的脚本,并检查它们是否匹配 RANDOM_STRING/user/folder。如果是这样,那么您可以将数据库中的随机字符串与通用文件夹匹配,例如 /user_files/username/their_folder。这样,您就不会暴露您的文件夹结构,并且您可以添加一个中间件来计算他们尝试 URL 失败的次数,然后如果超过 3 次则禁止他们的客户端,例如。

在这种情况下,脚本将文件(或文件夹)作为下载或作为屏幕提供,但实际文件夹结构不可见。这些文件可以存储在任何地方,并且数据库将输入的 URL 与某处的实际文件或文件夹相关联。 (真的,我们正在努力减少有人通过蛮力获得访问权限)。

从那里开始,我会考虑使用不同的服务来存储文件。这有助于您阅读两件事。首先,你可以选择像 AWS 冷存储这样的东西,它会降低你的成本,其次你可以把存储从计算服务器上拿下来,这样如果存在安全漏洞,你就知道他们要么只能访问用户文件,要么或代码文件。这将在很长一段时间内帮助你运行(尽管如果他们获得了你的代码文件的访问权限,他们将很可能能够找到你的存储位置和密码......这确实是为了保护你的代码文件)。

除此之外,开始研究读写权限和用户组。 PHP、OS、用户和管理员都应该对存储服务器拥有自己的权限,以确保他们不能对文件执行某些操作。此外,您不希望有人上传恶意文件并执行它。

这只是一本入门书,但我敢肯定,它会让您了解很多信息。

你必须区分 public 和私有文件。

Public 个文件

每个人都可以访问

Public 个文件,您猜对了。它们是图像、徽标、文档……这类文件。如果你有这些文件url,你可以下载它们。

私人文件

私人文件的情况稍微复杂一些。在任何情况下,这些文件都不应在未经身份验证的情况下下载。换句话说,只有拥有这些文件的用户(通常还有管理员)才能下载它们。例如,这些文件可能是您的订单发票、付费媒体...

对于目录结构,你随意,由你决定。唯一重要的是防止这些文件 public 只能访问,因此您 绝不能 将它们放在 public 文件夹中的某处(以及链接的 storage/app/public).

默认情况下,Laravel 期望这些文件在 storage/app 中。例如,对于 ID 为 1451 的用户,它可能是 storage/app/users/1451。随机化这些路径并不重要,因为这些文件无法直接访问(它们不在 public 路径中)。

所以您可能会问,用户如何下载它们?答案是创建经过身份验证的路由并在响应中发回文件之前检查用户授权。

您可以这样做:

Route::get('invoices/{invoice}/download', [InvoiceController::class, 'download']);

然后,您将策略应用于该路由,在其中检查经过身份验证的用户是否能够下载文件(就像您对任何其他经过身份验证的路由所做的那样)。

如果他可以,那么,完美,只需 return 响应中的文件:return response()->download($path_to_the_file);。如果他做不到,他将获得 403 Forbidden.