在 Laravel 專案中,用戶可以上傳任何大小的檔案,出于安全目的,需要對這些檔案進行靜態加密,
Laravel 提供 encryption, 但它們主要用于加密值, 使用 encrypt 助手方法對像影像這樣的小檔案進行加密可以很好地作業,但是在此程序中,檔案內容需要加載到記憶體中,這對于大檔案來說是個問題,
我已經搜索過用于解決此問題的軟體包或解決方案,并遇到了這個 Stack Overflow 回答和這個 PHP 解決方案,該解決方案基本上是 Stack Overflow 所描述的解決方案的 PHP 實作,
我決定創建一個為 Laravel 設計的擴展包,使用簡單,優雅的語法提供簡單的檔案加密 / 解密功能,
我將其稱為 FileVault 包,您可以 GitHub 上查看它, 如果您想跳過本教程,可以直接轉到 GitHub 存盤庫并開始使用此軟體包, 該擴展包包括了詳細的使用檔案,
教程
在這個教程中,我會詳細描述加密大檔案需要的所有步驟,
首先, 使用 Laravel 安裝器 創建一個新的 Laravel 專案, 命名為 security-app:
laravel new security-app
在撰寫本教程時,我正在使用 Laravel v6.5.2,
因為我們已經使用了 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" >
@csrf
<div >
<div >
<input type="file" id="userFile" name="userFile">
<label for="userFile">Choose a file</label>
</div>
</div>
<button type="submit" >Upload</button>
@if (session()->has('message'))
<div >
{{ session('message') }}
</div>
@endif
</form>
然后添加相應的路由:
Route::post(‘/home’, ‘HomeController@store’)->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}’, ‘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, 接收一個回呼.
在回呼中,我們正在呼叫擴展包 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 >
@forelse ($files as $file)
<li >
<a href="https://www.cnblogs.com/a609251438/p/{{ route('downloadFile', basename($file)) }}">
{{ basename($file) }}
</a>
</li>
@empty
<li >You have no files</li>
@endforelse
</ul>
就是這樣! 我們現在在使用靜態加密! 我們創建了供用戶上傳檔案的表單,對這些檔案進行加密,并且僅在上傳檔案的用戶要求時才對其解密,
當然,在生產中,需要采取更多的安全措施,而 FileVault 擴展包旨在這方面為您提供幫助,
如,您可能希望將用戶上傳的大檔案存盤在 Amazon S3 中,該擴展包支持檔案加密 / 流解密,
您可能還想為每個用戶或每個檔案使用不同的加密密鑰,這對于 FileVault 擴展包也是可能的,
資源
- 您可以在 GitHub 中找到在本教程中創建的整個 Laravel 應用.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/61856.html
標籤:PHP
