@H_301_0@我已经搜索过用于解决此问题的软件包或解决方案,并遇到了这个 Stack Overflow 回答和这个 PHP 解决方案,该解决方案基本上是 Stack Overflow 所描述的解决方案的 PHP 实现。
@H_301_0@我决定创建一个为 Laravel 设计的扩展包,使用简单,优雅的语法提供简单的文件加密 / 解密功能。
@H_301_0@我将其称为 FileVault 包,您可以 GitHub 上查看它。 如果您想跳过本教程,可以直接转到 GitHub 存储库并开始使用此软件包。 该扩展包包括了详细的使用文档。
教程
@H_301_0@在这个教程中,我会详细描述加密大文件需要的所有步骤。 @H_301_0@首先, 使用 Laravel 安装器 创建一个新的 Laravel 项目, 命名为security-app
:
laravel new security-app
@H_301_0@因为我们已经使用了 Laravel 安装程序,所以我们已经生成了一个应用程序密钥并将其添加到我们的 .env 文件中。 如果您使用其他安装方法,请不要忘记使用以下方法生成新的应用程序密钥:
@H_301_0@因为我们正在使用 Laravel Valet,所以应该已经为我们创建了 security-app.test 域名。 如果使用其他开发环境,则应添加一个本地域名指向新项目。
@H_301_0@由于自 Laravel 6 以来前端脚手架已被移至 Laravel UI 中,因此我们将安装 laravel/ui 扩展包。
composer require laravel/ui — dev
bootstrap
和 auth
脚手架:
@H_301_0@并编译所有内容:
npm install && npm run dev
@H_301_0@您可以使用一个非常好的扩展包是 pion/laravel-chunk-upload.
@H_301_0@Laravel Auth 脚手架为我们创建了一个 /home 路由,一个 HomeController 和一个 home.blade.PHP 视图文件。
@H_301_0@让我们编辑 home.blade.PHP 文件并添加一个表单和一个上传字段:
<form action="{{ route('uploadFile') }}" method="post" enctype="multipart/form-data" class="my-4"> @csrf <div class="form-group"> <div class="custom-file"> <input type="file" class="custom-file-input" id="userFile" name="userFile"> <label class="custom-file-label" for="userFile">Choose a file</label> </div> </div> <button type="submit" class="btn btn-primary">Upload</button> @if (session()->has('message')) <div class="alert alert-success mt-3"> {{ session('message') }} </div> @endif </form>
Route::post(‘/home’,‘HomeController@store’)->name(‘uploadFile’);
@H_301_0@注意:这是不正确的做法,不应在生产环境中使用。 为了使本教程更加小巧,我们使用文件系统来获取用户的文件,但是在生产环境中,需要使用数据库来跟踪每个用户上传的文件。
<?PHP /** * Store a user uploaded file * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { if ($request->hasFile('userFile') && $request->file('userFile')->isValid()) { Storage::putFile('files/' . auth()->user()->id,$request->file('userFile')); } return redirect()->route('home')->with('message','Upload complete'); }
composer require soarecostin/file-vault
@H_301_0@我们将使用 FileVault::encrypt($file) 方法来加密用户上传的文件。 此功能将删除原始的未加密文件,并将其替换为具有相同名称和附加 .enc 扩展名的文件。
@H_301_0@如果您想使用不同的名称命名文件,则可以将所需的名称作为第二个参数传递给 encrypt 方法。 如果您想保留原始文件,可以使用 encryptCopy 方法。
@H_301_0@这就是我们的 store 方法现在的样子:
<?PHP /** * Store a user uploaded file * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { if ($request->hasFile('userFile') && $request->file('userFile')->isValid()) { $filename = Storage::putFile('files/' . auth()->user()->id,$request->file('userFile')); // Check to see if we have a valid file uploaded if ($filename) { FileVault::encrypt($filename); } } return redirect()->route('home')->with('message','Upload complete'); }
@H_301_0@我们将在 HomeController 中创建一个新的 downloadFile 路由和一个新的 downloadFile 方法:
Route::get(‘/files/{filename}’,‘HomeController@downloadFile’)->name(‘downloadFile’);
<?PHP /** * Download a file * * @param string $filename * @return \Illuminate\Http\Response */ public function downloadFile($filename) { // Basic validation to check if the file exists and is in the user directory if (!Storage::has('files/' . auth()->user()->id . '/' . $filename)) { abort(404); } return response()->streamDownload(function () use ($filename) { FileVault::streamDecrypt('files/' . auth()->user()->id . '/' . $filename); },Str::replaceLast('.enc','',$filename)); }
downloadFile 使用 Laravel 原生的 streamDownload response,接收一个回调.
@H_301_0@在回调中,我们正在调用扩展包 FileVault 提供的 streamDecrypt 方法,它将对文件进行解密并将其逐段提供给
streamDownload
方法,从而允许您的用户直接下载解密文件。
@H_301_0@现在,我们需要在上传表单下方显示所有用户的文件。 为此,我们将 $files 变量从 HomeController 的 index 方法发送到 home.blade.PHP 视图文件,并在上传表格的下面显示用户文件。
<?PHP /** * Show the application dashboard. * * @return \Illuminate\Contracts\Support\Renderable */ public function index() { $files = Storage::files('files/' . auth()->user()->id); return view('home',compact('files')); }
<ul class="list-group"> @forelse ($files as $file) <li class="list-group-item"> <a href="{{ route('downloadFile',basename($file)) }}"> {{ basename($file) }} </a> </li> @empty <li class="list-group-item">You have no files</li> @endforelse </ul>
@H_301_0@您可能还想为每个用户或每个文件使用不同的加密密钥,这对于 FileVault 扩展包也是可能的。
资源
- 您可以在 GitHub 中找到在本教程中创建的整个 Laravel 应用.