【问题标题】:Upload, Store, and Download files with privacy restrictions in Laravel在 Laravel 中上传、存储和下载具有隐私限制的文件
【发布时间】:2018-09-03 18:19:56
【问题描述】:

我正在开发一个网站,管理员可以在其中上传文件(在仅限管理员的受限区域中)并将文件与用户相关联。 当普通用户登录网站时,他们将有一个“文档”部分,他们可以在其中查看上传并与他们关联的文件。

我在网上挖了很多,但所有的信息都让我感到困惑,所以我想问问大家:)

这是我基本上想要实现的目标:

  1. 管理员可以访问一个受限区域,她可以使用上传表单上传多个文件,并且对于每个文件,她可以选择与哪些用户关联文件。
    我希望能够创建一个表单,在任何更新发生之前,列出文件名和一个多选框,其中包含每个文件名附近的所有用户。

  2. 上传的文件将与一个或多个用户关联,并且用户可以与多个文件关联。即多对多关系。
    我想创建一个file_user 数据透视表,这样每个 File 类都可以与 User 类的许多实例相关联,反之亦然。 em>

  3. 文件名应保持原名,但应有可能出现重名。因此,我应该创建一些东西来区分文件并保持它们的唯一性(但仍然使用相同的文件名)。
    我想到了不同的文件夹名称,但它在服务器中会很乱。

  4. 用户应该能够访问和下载与其关联的文件。他们不应该能够访问与他们无关的文件,也不知道它的存在。 (即 File Not Found 而不是 Permission Denied)。


我已经实施了身份验证,并且我知道如何创建仅限管理员使用的页面。为了实现文件上传和下载服务,我想到了这样的事情:

  1. 使用迁移和控制器创建一个 File 模型
  2. 创建FileController@create(多文件上传表单视图)、FileController@store(将文件存储在数据库中)、FileController@index(处理用户看到与他们关联的文件并可以下载的视图他们)和FileController@download(负责将文件下载给授权用户)功能在FileController中。
  3. 为上述方法创建视图
  4. 在数据库中创建一个files 表(通过迁移)以包含file_idfile_name
  5. 创建一个 file_user 数据透视表,因为它们具有多对多特性。

我正在努力实现上述内容,将文件限制为允许的用户,我不确定这是最好和最安全的方法。

您将如何实现这一点?如果您有时间,如果您为每个阶段添加代码片段以便我能更好地理解,我将不胜感激。一个实现这一点的简单应用程序将是最好的学习方法。目前我在网上没有找到。

我很乐意详细说明并详细解释不清楚的部分。
谢谢!

【问题讨论】:

  • 成就点1、2明确。你得到了正确的方法。第 3 点有点棘手。我假设一个用户不能有 2 个同名的文件,但另一个用户可以有一个用户 1 也有的文件名。为此,我将创建一个将保存在服务器上的唯一文件名。这些唯一的文件名链接到用户文件名。在同一张桌子上。 (文件名,filename_token)。
  • 对于数字3,虽然有很多选项,但最简单的方法之一是在文件名末尾附加时间以使其唯一,如$fileName.'_'.time().'.'.$extenstion
  • 是的,当然,如果用户下载文件,您希望显示文件名,而不是令牌。这很简单` `
  • 对于数字 4,如果请求的文件与用户 ID 无关,您可以简单地重定向到另一个页面或 404 页面

标签: php laravel security laravel-5 file-upload


【解决方案1】:

很难回答所有本应单独提出的问题。我不会详细说明所有事情,而是会提醒您经常打嗝的地方。

如果文件命名我坚持让你让它自动生成。请务必为包含原始名称的文件模型添加额外的可填充项。使用此行从请求中获取原始文件名:

$fileName = time().'_'.$req->file->getClientOriginalName();

然后可以在下载时再次访问此名称,然后在调用下载函数时将其作为参数传递给“名称”参数。

用户和文件之间的数据透视表只需要数据库文件夹中的迁移文件。在分配 ID 时,我强烈建议使用 Uuid。使用 Traits 将其添加到您的模型中轻而易举 https://www.larashout.com/using-uuids-in-laravel-models

文件页面迁移

Schema::create('file_pages', function(Blueprint $table) {
    $table->uuid('id')->primary();
    $table->string('title')->nullable(true);
    $table->text('body')->nullable(true);
    $table->timestamps();
});

文件迁移

Schema::create('files', function(Blueprint $table) {
    $table->id();
    //$table->foreignId('file_page_id')->constrained();
    $table->uuid('file_page_id')->nullable(true);
    $table->foreign('file_page_id')->references('id')->on('file_pages')->onDelete('cascade');
    $table->string("name")->nullabe();
    $table->string("page_path")->nullabe();
    $table->string("view_name")->nullabe();
    $table->string("file_path")->nullable();
    $table->timestamps();
});

记得为使用你的 Uuid trait 的模型设置 public $incrementing=false;

在您看来,您可以私下和公开地为您的用户提供文件。鉴于您配置了 config/filesystems.php,请在 bash 终端中运行“php artisan storage:link”,并且可能还会清除您的存储缓存。这是一个非常简单的事情,可以帮助您入门:

<audio controls>
    <source src="{{asset($file->file->file_path)}}" type="audio/mp3">
</audio>
<a href="{{asset($file->file->file_path)}}" type="audio/mp3"></a>

音频播放文件。锚标记下载它(使用生成的文件名文件名)。

对于页面等的条件行为,我会阅读这个帖子: How can I require authentication in Laravel 5 on a conditional basis? 一旦你学会了这一点,你就可以在以后的职业生涯中调整你的知识来制作更多的身份验证中间件

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 2015-01-05
    • 2020-03-09
    • 2016-05-04
    相关资源
    最近更新 更多