你的 API 像公共廁所隨便進?Laravel 11 驗證 (Validation) 與 Middleware 客製化終極實戰,打造駭客絕望的銅牆鐵壁

2026/01/4 | Laravel技術分享, 全端與程式開發, 網站安全與防護

駭客絕望!Laravel 11 打造 API 銅牆鐵壁的雙重門神

後端工程師常因「偷懶」忽略資料驗證,導致系統暴露於致命風險。本文以 Laravel 11 為核心,教您如何運用 Form Request 告別混亂的 Controller,實踐關注點分離;並透過客製化 Middleware 迎戰 Laravel 11 新架構,建立 API 的第一道警衛室。我們將深入探討 Middleware 與 Validation 的雙重防線,徹底杜絕髒資料與未授權存取。別再讓您的 API 裸奔!立即升級系統防護,聯繫浪花科技,由資深工程師為您終結技術債。

需要專業協助?

聯絡浪花專案團隊 →

你的 API 像公共廁所隨便進?Laravel 11 驗證 (Validation) 與 Middleware 客製化終極實戰,打造駭客絕望的銅牆鐵壁

嘿,我是 Eric,浪花科技的資深工程師。今天我們要來聊聊後端工程師最容易「偷懶」,但也是最致命的環節:資料驗證 (Validation)中介層 (Middleware)

在 Code Review 的時候,我最常對 Junior 工程師說的一句話就是:「永遠不要相信前端傳來的資料,就算那個前端是你自己寫的也一樣。」很多新手會覺得,反正前端表單已經有擋必填了,後端直接存進資料庫就好啦?錯!大錯特錯!這就像是你家大門沒鎖,只掛了一個「請勿進入」的牌子一樣,駭客(或者只是調皮的使用者)只要用 Postman 或 cURL 繞過前端,就能把你的資料庫變成垃圾場,甚至發動 SQL Injection 攻擊。

在這篇文章中,我將以 Laravel 11 為基礎(沒錯,我們要跟上最新版本,別再抱著 Kernel.php 不放了),帶你深入探討如何透過 Laravel 驗證與 Middleware 客製化,打造出滴水不漏的 API 防護網。我們會從 Form Request 的優雅寫法,一路講到 Laravel 11 最新的 Middleware 註冊方式。

為什麼我們需要「雙重驗證」機制?

在討論技術細節前,我們要先建立正確的觀念。一個健壯的後端架構,通常會有兩道門神:

  • 第一道防線:Middleware (中介層)
    這是 API 的「警衛室」。它不負責檢查你帶了什麼行李(資料),而是檢查「你是誰」以及「你有沒有資格進來」。例如:身份驗證 (Auth)、權限檢查 (RBAC)、頻率限制 (Rate Limiting) 以及 CORS 設定。
  • 第二道防線:Validation (驗證邏輯)
    這是 API 的「安檢門」。當你通過警衛室後,我們要打開你的行李,檢查裡面的資料是否符合規定。例如:Email 格式對不對?密碼強度夠不夠?這個 Coupon Code 是否存在?

如果這兩層沒做好,你的 Controller 就會充滿了髒 code,既難維護又充滿漏洞。接下來,我們就來實戰操作。

Laravel 驗證 (Validation) 進階實戰:拒絕髒資料

1. 告別 Controller 裡的 $request->validate()

很多教學會教你在 Controller 裡直接寫驗證邏輯:

// ❌ 這種寫法是這維護惡夢的開始
public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|max:255',
        'body' => 'required',
    ]);

    // 業務邏輯...
}

雖然這樣寫很快,但當規則一多,你的 Controller 就會變得像一坨義大利麵。身為資深工程師,我們追求的是「關注點分離 (Separation of Concerns)」。請愛用 Form Request

在終端機輸入:

php artisan make:request StorePostRequest

這會在 app/Http/Requests 產生一個檔案。我們可以在這裡定義規則:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePostRequest extends FormRequest
{
    public function authorize(): bool
    {
        // 這裡可以做簡單的權限判斷,例如只有管理員能發文
        return true; 
    }

    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:255'],
            'slug'  => ['required', 'string', 'unique:posts,slug'],
            'status' => ['required', 'in:draft,published,archived'],
            'author_id' => ['required', 'exists:users,id'], // 確保關聯資料存在
        ];
    }

    // 自訂錯誤訊息,讓前端工程師感謝你
    public function messages(): array
    {
        return [
            'slug.unique' => '這個網址代稱已經被用過了,換一個吧!',
            'author_id.exists' => '找不到這位作者,請確認 ID 是否正確。',
        ];
    }
}

然後,在你的 Controller 只需要這樣寫:

public function store(StorePostRequest $request)
{
    // 程式執行到這裡時,保證資料已經驗證通過並經過過濾
    // 你的 Controller 瞬間清爽了 50%!
    
    $data = $request->validated();
    
    Post::create($data);
    
    return response()->json(['message' => '發布成功']);
}

2. 進階技巧:自訂驗證規則 (Custom Rules)

有些時候,Laravel 內建的規則不夠用。例如,你需要驗證一個「台灣手機號碼」格式(09開頭,共10碼)。這時候別在 Controller 寫 regex,請建立一個 Rule:

php artisan make:rule TaiwanPhoneNumber

在 Laravel 11 中,預設是產生 Invokable Rule,寫法非常簡潔:

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

class TaiwanPhoneNumber implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (!preg_match('/^09\d{8}$/', $value)) {
            $fail("The :attribute must be a valid Taiwan phone number.");
        }
    }
}

使用方式:

use App\Rules\TaiwanPhoneNumber;

// 在 Form Request 中
'phone' => ['required', new TaiwanPhoneNumber],

Middleware 客製化:Laravel 11 的變革

來到 Middleware 客製化 的部分。如果你是從舊版本升級上來的,這部分要注意了。Laravel 11 移除了 app/Http/Kernel.php,Middleware 的註冊方式改到了 bootstrap/app.php

假設我們要寫一個 Middleware,用來檢查 Request Header 是否包含特定的 API Key(這在跟第三方廠商串接時很常見)。

1. 建立 Middleware

php artisan make:middleware CheckApiKey

編輯 app/Http/Middleware/CheckApiKey.php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CheckApiKey
{
    public function handle(Request $request, Closure $next): Response
    {
        // 檢查 Header 中的 X-API-KEY
        $apiKey = $request->header('X-API-KEY');

        if ($apiKey !== env('MY_SECRET_API_KEY')) {
            // 如果不符,直接退貨,連 Controller 都不讓他進
            return response()->json(['error' => 'Unauthorized: Invalid API Key'], 401);
        }

        return $next($request);
    }
}

2. 在 Laravel 11 中註冊 Middleware

現在,打開 bootstrap/app.php,這是新的控制中心:

use App\Http\Middleware\CheckApiKey;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

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([
            'api.key' => CheckApiKey::class,
        ]);

        // 或者,如果你想要全域套用 (Global Middleware)
        // $middleware->append(CheckApiKey::class);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

3. 在 Route 中使用

註冊完別名後,就可以在 routes/api.php 輕鬆掛上去了:

Route::middleware(['api.key'])->group(function () {
    Route::post('/secure-data', [SecureController::class, 'store']);
});

Eric 的開發小叮嚀 (Best Practices)

結合了 Laravel 驗證與 Middleware 客製化,你的 API 安全性已經贏過 80% 的網站了。但身為過來人,Eric 還有幾點要囉嗦一下:

  1. 不要依賴前端驗證: 前端驗證只是為了提升使用者體驗 (UX),讓使用者不用等到送出表單才知道填錯了。後端驗證才是真正的守門員。
  2. 善用 prepareForValidation 在 Form Request 中,你可以使用 prepareForValidation 方法來先處理資料。例如把 email 轉小寫,或是把全形數字轉半形,再進行驗證,這能大幅減少資料髒亂的機會。
  3. 回傳統一的錯誤格式: 當 Middleware 攔截或 Validation 失敗時,確保回傳的 JSON 結構是一致的。不要一下回傳 {"error": "msg"},一下回傳 {"message": "msg"},前端工程師會想拿鍵盤丟你。

相關閱讀

想要打造更完美的 Laravel 系統?這裡有三篇我精選的進階文章,強烈建議延伸閱讀:

如果你發現公司的 API 像是一團混亂的毛線球,或者每次修改驗證邏輯都要改動五六個檔案,那代表你們的系統架構需要「進廠維修」了。

浪花科技 專注於高強度的 Laravel 系統開發與 WordPress 客製化。我們不只寫 Code,更在乎系統的可維護性與安全性。如果你有任何技術債需要處理,或者想打造企業級的 Web 應用,歡迎聯繫我們。

不想讓你的 API 裸奔?讓專業的來幫你把關!

點擊下方按鈕,填寫表單,Eric 會親自與你評估專案需求。

立即聯繫浪花科技

常見問題 (FAQ)

Q1: Laravel 11 的 Middleware 寫法跟舊版有什麼最大的不同?

最大的不同在於註冊位置。Laravel 11 移除了 app/Http/Kernel.php,改為在 bootstrap/app.php 中使用 ->withMiddleware() 方法來註冊全域 Middleware 或別名 (Alias)。這讓專案結構更簡潔,但也需要適應新的配置方式。

Q2: 為什麼建議使用 Form Request 而不是在 Controller 裡驗證?

使用 Form Request 符合「單一職責原則 (SRP)」。Controller 應該專注於處理請求的流程與回應,而不該被大量的驗證規則佔據。Form Request 讓驗證邏輯可被重複利用,且支援 authorize 權限檢查與自訂錯誤訊息,能讓程式碼更乾淨、易讀且好維護。

Q3: 如果驗證失敗,Laravel 預設會發生什麼事?

如果是 API 請求(Header 帶有 Accept: application/json),Laravel 會自動捕捉 ValidationException 並回傳 HTTP 422 Unprocessable Entity 狀態碼,以及包含錯誤欄位訊息的 JSON。這也是為什麼我們不需要手動寫 try-catch 來處理驗證錯誤,Laravel 已經幫我們處理好了。

 
立即諮詢,索取免費1年網站保固