Laravel框架中怎么对大文件进行加密,file-vault扩展包了解一下
在Laravel项目中,用户可以上传任何大小的文件,出于安全目的,需要对这些文件进行静态加密。
在这个教程中,我会详细描述加密大文件需要的所有步骤。
首先, 使用 Laravel 安装器 创建一个新的 Laravel 项目, 命名为 security-app:
laravel new security-app
在撰写本教程时,我正在使用 Laravel 6+。
因为我们已经使用了 Laravel 安装程序,所以我们已经生成了一个应用程序密钥并将其添加到我们的 .env 文件中。
如果您使用其他安装方法,请不要忘记使用以下方法生成新的应用程序密钥:
PHP artisan key:generate
因为我们正在使用 Laravel Valet,所以应该已经为我们创建了 security-app.test 域名。
如果使用其他开发环境,则应添加一个本地域名指向新项目。
由于自 Laravel 6 以来前端脚手架已被移至 Laravel UI 中,因此我们将安装 laravel/ui 扩展包。
composer require laravel/ui — dev
接下来,我们将安装 bootstrap 和 auth 脚手架:
PHP artisan ui bootstrap --auth
并编译所有内容:
npm install && npm run dev
我们还需要在 .env 文件中配置数据库访问凭据并运行初始迁移:
PHP artisan migrate
现在,我们可以创建一个新用户并登录查看用户仪表板。
注意:在本演示中,我们将创建一个基本的上传表单,但是在您的应用程序中,您应该考虑使用更复杂的上传功
能,对大文件使用分块上传。
您可以使用一个非常好的扩展包是 pion/laravel-chunk-upload.
Laravel Auth 脚手架为我们创建了一个 /home 路由,一个 HomeController 和一个 home.blade.PHP 视图文件。
让我们编辑 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’,‘[email protected]’)->name(‘uploadFile’);
在 HomeController 中新增 store 方法。
此方法会将上传的文件存储在具有当前用户 ID 的文件目录中 (storage/app/files/{user-id}) 。
注意:这是不正确的做法,不应在生产环境中使用。
为了使本教程更加小巧,我们使用文件系统来获取用户的文件,
但是在生产环境中,需要使用数据库来跟踪每个用户上传的文件。
<?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');
}
到了加密用户上传文件 的阶段。我们将安装 file-vault 扩展包:
composer require soarecostin/file-vault
该软件包允许访问 FileVault 门面, 其中提供了一些用于加密和解密文件的方法,还提供了一些方法来设置选项,
例如为每个文件设置不同的加密密钥,或指定该文件的 Laravel 文件系统磁盘。
我们将使用 FileVault::encrypt($file) 方法来加密用户上传的文件。
此功能将删除原始的未加密文件,并将其替换为具有相同名称和附加 .enc 扩展名的文件。
如果您想使用不同的名称命名文件,则可以将所需的名称作为第二个参数传递给 encrypt 方法。
如果您想保留原始文件,可以使用 encryptCopy 方法。
这就是我们的 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');
}
接下来,我们需要查看所有用户上传的文件,还需要一种下载它们的方法。
我们将在 HomeController 中创建一个新的 downloadFile 路由和一个新的 downloadFile 方法:
Route::get(‘/files/{filename}’,‘[email protected]’)->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,接收一个回调.
在回调中,我们正在调用扩展包 FileVault 提供的 streamDecrypt 方法,
它将对文件进行解密并将其逐段提供给 streamDownload 方法,从而允许您的用户直接下载解密文件。
现在,我们需要在上传表单下方显示所有用户的文件。
为此,我们将 $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'));
}
home.blade.PHP
<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>
就是这样! 我们现在在使用静态加密!
我们创建了供用户上传文件的表单,对这些文件进行加密,并且仅在上传文件的用户要求时才对其解密。
当然,在生产中,需要采取更多的安全措施,而 FileVault 扩展包旨在这方面为您提供帮助。
如,您可能希望将用户上传的大文件存储在 Amazon S3 中,该扩展包支持文件加密 / 流解密。
您可能还想为每个用户或每个文件使用不同的加密密钥,
这对于 FileVault 扩展包也是可能的。
完
相关文章