Laravel从php输出缓冲区VS下载文件。私人存储文件夹| 安全

Rom*_*man 12 php security download laravel

用户可以下载CSV格式的查询结果。该文件很小(几个KB),但是内容很重要。

第一种方法是使用php输出缓冲区php://

$callback = function() use ($result, $columns) {
    $file = fopen('php://output', 'w');
    fputcsv($file, $columns);

    foreach($result as $res) {
        fputcsv($file, array($res->from_user, $res->to_user, $res->message, $res->date_added));
    }
    fclose($file);
};

return response()->stream($callback, 200, $headers);
Run Code Online (Sandbox Code Playgroud)

第二种方法是在laravels存储系统中创建一个新文件夹,并将其设置为private,然后从那里下载文件。下载后,您甚至可以删除文件:

'csv' => [
    'driver' => 'local',
    'root' => storage_path('csv'),
    'visibility' => 'private',
],
Run Code Online (Sandbox Code Playgroud)

这是创建/下载代码:

$file = fopen('../storage/csv/file.csv', 'w');
fputcsv($file, $columns);

foreach($result as $res) {
    fputcsv($file, array($res->from_user, $res->to_user, $res->message, $res->date_added));
}
fclose($file);

return response()->make(Storage::disk('csv')->get('file.csv'), 200, $headers);
Run Code Online (Sandbox Code Playgroud)

下载后,此返回将立即删除文件:

return response()->download(Storage::disk('csv')->path('file.csv'))
->deleteFileAfterSend(true);
Run Code Online (Sandbox Code Playgroud)

有什么会更安全?有什么更好的方法?我目前倾向于使用存储的第二种方法。

tan*_*kay 5

选项1

原因:

  • 您没有保留文件,因此持久存储到磁盘的用途受到限制
  • 数据量很小,因此下载失败不太可能发生,并且如果发生这种情况,则重新创建输出的处理时间也非常短(我假设这是幕后的快速SQL查询?)
  • 将文件保存在存储中会为文件复制创造机会,您将来可能会设置的增量备份或rsync可能会在敏感文件被删除之前复制它们...
  • 从文件系统中删除文件并不一定会使数据无法恢复

如果您要处理的文件大小为几十MB /几百MB,那么我会有所不同...


Eug*_*rov 2

我认为回复取决于当前的架构和要下载的文件的大小

(1)st 方法适用于以下情况:

  • 如果文件很小(小于 10 Mb),谢谢 @tanerkay

  • 你有简单的架构(例如 1 个服务器)

理由:

  • 没有下载失败——无需重试

  • 把事情简单化

  • 没有文件=没有备份,没有rsync,也没有其他地方可以窃取它

。。。

(2)第一种方法适用于:

  • 如果您的文件很大(10+ Mb)

  • 如果您已经拥有具有多个平衡加载器的微服务架构 - 保持相似性

  • 如果您有数百万用户尝试下载 - 如果没有平衡加载器和并行下载,您就无法为他们提供服务

理由:

  • 第二种方法肯定更具可扩展性,因此在高负载下更稳定,因此更安全。微服务更耗时,并且对于重负载来说更具可扩展性。

  • 使用单独的文件存储允许您将来拥有单独的文件服务器和负载平衡以及队列管理器和单独的专用访问控制。

  • 如果内容很重要,通常意味着获取它对于用户来说非常重要。但是直接带有标头的输出可能会挂起或出现超时错误等。我认为,保留文件直到下载为止是更可靠的交付方法。

尽管如此,我还是考虑了过期时间,而不是下载事实,或者除了下载事实之外——下载过程可能会失败,或者文件丢失(确保 1 小时以上的可用性),反之亦然,用户只会在 1 年后尝试下载它,或者从不下载 - - 为什么你要把这个文件保留N天以上?

  • 为什么它会更安全?增加解决方案的复杂性(文件系统、单独存储、负载平衡器)会增加攻击面,直观上会导致安全性降低。把事情简单化... (2认同)