Laravel 11 終極防線:拒絕髒資料!
告別義大利麵防線!資深工程師教你在 Laravel 11 中,如何以 Middleware 執行保全任務,用 Form Request 確保資料純淨。後端絕不能裸奔,前端驗證擋不住駭客!立即掌握 Laravel 11 的架構新制,將驗證與權限分離,打造高效且穩固的 API 城堡。別讓技術債拖垮業務,立即聯繫我們,重構出藝術品般的程式碼!
拒絕髒資料進門!Laravel 11 終極驗證 (Validation) 與客製化中介層 (Middleware) 實戰攻略
嗨大家,我是 Eric,浪花科技 (Roamer Tech) 的資深工程師。今天不聊那些飄在天上的 AI 概念,我們要來聊點「硬核」且每天都會遇到的後端生存法則。
你是否曾經接手過這種專案:打開 Controller,迎面而來的是幾十行的 if-else 判斷?
- 「如果有
email欄位…」 - 「如果
password大於 6 個字…」 - 「如果這個使用者是管理員…」
這種寫法我稱之為「義大利麵防線」,看起來有在擋,但隨便戳一下就破了,而且維護起來簡直是地獄。在 Laravel 的世界裡,我們有兩把屠龍刀可以優雅地解決這個問題:驗證 (Validation) 與 中介層 (Middleware)。
特別是到了 2025 年,Laravel 11 在架構上做了不小的瘦身(移除了許多預設 config 檔案),很多原本寫在 Kernel.php 的設定現在都搬到了 bootstrap/app.php。這篇文章我將會用最新的 Laravel 11 觀念,帶你打造銅牆鐵壁般的 API。
為什麼你的 API 像是在「裸奔」?
很多初階工程師會覺得:「反正前端有做表單驗證了,後端隨便寫寫就好。」
大錯特錯!
前端驗證是用來「提升使用者體驗」的,不是用來「防駭客」的。任何人都可以透過 Postman 或 cURL 直接對你的 API 發送請求,繞過所有的前端驗證。如果你的 Laravel 後端沒有做好把關,惡意資料就會像喪屍一樣湧入你的資料庫。
Middleware vs. Validation:誰負責什麼?
在開始寫 Code 之前,我們要先釐清觀念,這也是很多面試會考的題目:
- Middleware (中介層): 像是大樓的保全。他不管你包包裡裝什麼,他只看你有沒有識別證 (Token)、是不是被列入黑名單 (IP Ban)、或是現在是不是開放時間 (Rate Limiting)。
- Validation (驗證): 像是櫃檯的行政人員。保全放你進來後,行政人員會檢查你的申請表 (Request Data) 有沒有填寫正確、Email 格式對不對、商品庫存夠不夠。
第一道防線:客製化 Middleware (Laravel 11 新制)
假設我們有一個需求:只有來自特定合作夥伴 API Key 的請求才能存取我們的特定路由。
首先,我們建立一個 Middleware:
php artisan make:middleware CheckPartnerApiKey
接著,打開產生的 app/Http/Middleware/CheckPartnerApiKey.php。我們要檢查 Header 裡是否有正確的 Key。
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CheckPartnerApiKey
{
/**
* Handle an incoming request.
*/
public function handle(Request $request, Closure $next): Response
{
$validApiKey = config('services.partner.api_key'); // 建議將 Key 放在 .env 並透過 config 讀取
$requestApiKey = $request->header('X-Partner-Key');
if ($requestApiKey !== $validApiKey) {
return response()->json([
'status' => 'error',
'message' => 'Unauthorized: Invalid API Key',
], 401);
}
return $next($request);
}
}
Laravel 11 的註冊方式變革
在 Laravel 10 以前,我們會去 app/Http/Kernel.php 註冊。但在 Laravel 11,Kernel.php 已經消失了!現在我們要在 bootstrap/app.php 進行設定,這是一個更簡潔的現代化做法。
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use App\Http\Middleware\CheckPartnerApiKey;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
// 註冊別名 (Alias),方便在 Route 中使用
$middleware->alias([
'partner.auth' => CheckPartnerApiKey::class,
]);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
現在,你就可以在 routes/api.php 中輕鬆使用了:
Route::middleware(['partner.auth'])->group(function () {
Route::post('/partner/sync', [PartnerController::class, 'syncData']);
});
第二道防線:Form Request Validation (表單請求驗證)
Middleware 擋掉了閒雜人等,接下來要處理資料正確性。請絕對不要在 Controller 裡面寫 $request->validate([...]),那會讓你的 Controller 變得非常肥大且難以閱讀。請使用 Form Request。
假設我們要建立一個「新增產品」的 API。
php artisan make:request StoreProductRequest
打開 app/Http/Requests/StoreProductRequest.php,這裡有兩個核心方法:authorize() 和 rules()。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreProductRequest extends FormRequest
{
/**
* 判斷使用者是否有權限執行此請求
*/
public function authorize(): bool
{
// 這裡可以整合 Policy,例如:
// return $this->user()->can('create', Product::class);
return true;
}
/**
* 定義驗證規則
*/
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'sku' => ['required', 'string', 'unique:products,sku'], // 檢查資料庫唯一性
'price' => ['required', 'numeric', 'min:0'],
'categories' => ['required', 'array', 'min:1'],
'categories.*' => ['exists:categories,id'], // 檢查陣列中的每個 ID 是否存在於資料庫
'is_active' => ['boolean'],
];
}
/**
* 自訂錯誤訊息 (可選,適合多語系或更友善的提示)
*/
public function messages(): array
{
return [
'sku.unique' => '這組 SKU 已經有人用過了,請換一組吧!',
'categories.*.exists' => '您選取的分類不存在,請重新整理頁面。',
];
}
}
在 Controller 中使用
這就是最迷人的地方。當你將 Type Hint 指定為你剛剛建立的 StoreProductRequest 時,Laravel 會自動在進入 Controller 方法之前執行驗證。如果驗證失敗,它會自動回傳 JSON 格式的 422 錯誤訊息,Controller 的程式碼一行都不會被執行!
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreProductRequest;
use App\Models\Product;
use Illuminate\Http\JsonResponse;
class ProductController extends Controller
{
public function store(StoreProductRequest $request): JsonResponse
{
// 能進到這裡,代表資料絕對是乾淨、正確的
// 不需要再寫任何 if-else 檢查欄位
// 直接取用驗證過的資料
$validated = $request->validated();
$product = Product::create($validated);
return response()->json($product, 201);
}
}
看,你的 Controller 是不是清爽到想哭?這就是「關注點分離 (Separation of Concerns)」的藝術。
進階技巧:自訂驗證規則 (Custom Rules)
有時候,Laravel 內建的規則不夠用。例如,你的電商系統規定:「如果是預購商品 (Pre-order),出貨日期必須在 30 天以後」。這時候就需要自訂規則。
php artisan make:rule PreOrderDateCheck
編寫邏輯:
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Carbon\Carbon;
class PreOrderDateCheck implements ValidationRule
{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
// 假設 request 中有另一個欄位叫 type
if (request()->input('type') === 'pre_order') {
$date = Carbon::parse($value);
if ($date->diffInDays(now()) < 30) {
$fail('預購商品的 :attribute 必須設定在 30 天之後。');
}
}
}
}
然後在 Form Request 中使用:
use App\Rules\PreOrderDateCheck;
// ... inside rules array
'shipping_date' => ['required', 'date', new PreOrderDateCheck],
結論:寫出優雅的 Code,晚上睡得比較好
作為一名資深工程師,我深信「防禦性程式設計 (Defensive Programming)」的核心不在於你寫了多少複雜的邏輯,而在於你如何利用框架提供的工具,把不乾淨的資料擋在門外。
利用 Laravel 11 的 Middleware 來管理存取權限,利用 Form Request 來確保資料完整性,你的應用程式將會變得像一座堅固的城堡。駭客進不來,髒資料進不來,你的 Controller 就能專心地處理商業邏輯,而不是在那邊當清潔工。
推薦閱讀
如果你對 Laravel 的架構安全與資料處理有興趣,強烈建議你延伸閱讀以下幾篇我精選的文章,這能讓你的技術視野更上一層樓:
- API 金鑰之亂終結者:Laravel + JWT 深度實戰,打造無狀態認證的現代化後端!
- 肥 Controller 瘦不下來?Laravel 後台架構終極對決:Repository vs. Service vs. Action 模式
- 不只是單向拋接!Laravel x HubSpot 進階戰術:打造企業級雙向、容錯、高效率的資料流引擎
如果你發現你的 Laravel 專案已經變成一團難以維護的義大利麵,或者你需要企業級的 API 架構規劃,別猶豫,讓我們來幫你重構出藝術品般的程式碼。
需要專業的 Laravel 架構諮詢嗎?
浪花科技擁有豐富的 Laravel 企業級開發經驗,從高流量 API 到複雜的 SaaS 系統,我們都能提供最穩健的解決方案。別讓技術債拖垮你的業務成長!
常見問題 (FAQ)
Q1: Middleware 和 Validation 的最大差別是什麼?
簡單來說,Middleware 是檢查「你能不能進來」(權限、頻率、IP),而 Validation 是檢查「你帶的東西對不對」(欄位格式、數值範圍)。Middleware 通常在 Controller 之前執行,擋掉不合法的請求者;Validation 則確保進入 Controller 處理邏輯的資料是安全且正確的。
Q2: Laravel 11 的 Middleware 設定為什麼找不到 Kernel.php?
這是 Laravel 11 的重大更新之一!為了簡化目錄結構,Laravel 11 移除了 app/Http/Kernel.php,所有的 Middleware 設定(全域、群組、別名)現在都統一在 bootstrap/app.php 檔案中使用 withMiddleware 方法來配置。
Q3: 為什麼不建議在 Controller 裡面直接寫 $request->validate()?
雖然這樣寫很快,但違反了單一職責原則 (SRP)。Controller 應該只負責調度邏輯,不該包含繁雜的驗證規則。將驗證邏輯移到 Form Request 類別中,不僅可以讓 Controller 更乾淨,還能讓驗證規則在不同的請求中被重複利用。






