# Laravel Middleware เจาะลึก: Authentication, Rate Limiting และ Custom Middleware ฉบับสมบูรณ์ > คู่มือเจาะลึก Laravel Middleware ครอบคลุมการทำงานของ Authentication Middleware, Rate Limiting ด้วย Throttle, การสร้าง Custom Middleware และการลงทะเบียน Middleware ใน Laravel 12 พร้อมตัวอย่างโค้ดที่ใช้งานได้จริงในโปรดักชัน - Published: 2026-04-16 - Updated: 2026-04-16 - Author: SharpSkill - Tags: laravel, middleware, authentication, rate-limiting, php - Reading time: 10 min --- Laravel Middleware ทำหน้าที่เป็นชั้นกรอง (Filtering Layer) ระหว่าง HTTP Request ที่เข้ามาและ Application Logic ทุก Request จะถูกส่งผ่าน Pipeline ของ Middleware Class ก่อนจะถึง Controller และทุก Response จะเดินทางกลับผ่าน Pipeline เดียวกัน การทำความเข้าใจกลไกนี้ถือเป็นสิ่งจำเป็นสำหรับการพัฒนา Laravel Application ที่มีความปลอดภัยและประสิทธิภาพสูงในปี 2026 > **Middleware โดยสรุป** > > Middleware ทำหน้าที่ดักจับ HTTP Request ก่อนที่จะถึง Route โดย Laravel 12 ลงทะเบียน Middleware ทั้งหมดใน `bootstrap/app.php` ผ่าน Fluent API ส่วน Built-in Middleware จะจัดการเรื่อง Authentication, CSRF Protection, Session Management และ Rate Limiting ให้โดยอัตโนมัติ ## Pipeline ของ Laravel Middleware ทำงานอย่างไร Laravel HTTP Kernel ประมวลผลทุก Request ผ่าน Stack ของ Middleware โดย Middleware แต่ละตัวจะรับ Request เข้ามา ดำเนินการตามตรรกะของตน จากนั้นส่ง Request ต่อไปยังชั้นถัดไปผ่าน `$next($request)` หรือตัดวงจร Pipeline ด้วยการคืนค่า Response โดยตรง สถาปัตยกรรมนี้เป็นไปตาม Chain of Responsibility Pattern โดย Middleware สามารถทำงาน **ก่อน** ที่ Request จะถึง Controller (เช่น การตรวจสอบ Authentication) ทำงาน **หลัง** จากที่ Response ถูกสร้างขึ้น (เช่น การเพิ่ม Header) หรือทำงานทั้งสองช่วงเวลา ```php // app/Http/Middleware/LogRequestTime.php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Symfony\Component\HttpFoundation\Response; class LogRequestTime { public function handle(Request $request, Closure $next): Response { $start = microtime(true); // Capture start time $response = $next($request); // Pass to next middleware $duration = microtime(true) - $start; Log::info('Request completed', [ 'url' => $request->url(), 'method' => $request->method(), 'duration' => round($duration * 1000, 2) . 'ms', ]); return $response; // Return response up the stack } } ``` Middleware ตัวนี้ครอบ Request ไว้ทั้งสองด้าน กล่าวคือจะบันทึกเวลาเริ่มต้น **ก่อน** การประมวลผล และบันทึกระยะเวลา **หลัง** จากที่ Response ถูกส่งกลับมา รูปแบบ Before/After นี้เป็นหัวใจสำคัญของการทำงานของ Middleware ## Authentication Middleware: การปกป้อง Route Laravel มาพร้อมกับ `auth` Middleware Alias ซึ่ง Map ไปยัง `Illuminate\Auth\Middleware\Authenticate` การใช้งาน Middleware นี้กับ Route ใดก็ตามจะทำให้มั่นใจได้ว่าเฉพาะผู้ใช้ที่ผ่านการยืนยันตัวตนแล้วเท่านั้นที่สามารถเข้าถึงได้ ผู้ใช้ที่ไม่ได้ยืนยันตัวตนจะได้รับ 401 Response (API) หรือถูก Redirect ไปยังหน้า Login (Web) ```php // routes/web.php use App\Http\Controllers\DashboardController; use App\Http\Controllers\ProfileController; // Single route protection Route::get('/dashboard', [DashboardController::class, 'index']) ->middleware('auth'); // Group protection for multiple routes Route::middleware('auth')->group(function () { Route::get('/profile', [ProfileController::class, 'show']); Route::put('/profile', [ProfileController::class, 'update']); Route::delete('/profile', [ProfileController::class, 'destroy']); }); ``` ### Multi-Guard Authentication Application ที่มีผู้ใช้หลายประเภท (Admin Panel, Customer Area, API) จะได้รับประโยชน์จากการยืนยันตัวตนแบบ Guard-Based โดย `auth` Middleware รับพารามิเตอร์ Guard เพื่อระบุว่าจะใช้ Authentication Driver ตัวใด ```php // routes/api.php // API routes use the 'sanctum' guard Route::middleware('auth:sanctum')->group(function () { Route::get('/user', fn (Request $request) => $request->user()); Route::apiResource('/orders', OrderController::class); }); // routes/web.php // Admin routes use a custom 'admin' guard Route::middleware('auth:admin')->prefix('admin')->group(function () { Route::get('/dashboard', [AdminController::class, 'index']); Route::get('/users', [AdminController::class, 'users']); }); ``` พารามิเตอร์ Guard หลังเครื่องหมาย Colon จะบอก Laravel ว่าให้ตรวจสอบกับ Authentication Configuration ตัวใด วิธีนี้ช่วยให้ตรรกะการยืนยันตัวตนเป็นระเบียบและแยกส่วนกันอย่างชัดเจนในแต่ละส่วนของ Application > **Guest Middleware** > > `guest` Middleware เป็นตรงข้ามของ `auth` กล่าวคือจะอนุญาตให้เฉพาะผู้ใช้ที่ยังไม่ได้ยืนยันตัวตนผ่านเข้าไปได้เท่านั้น การนำไปใช้กับ Route ของหน้า Login และ Registration จะป้องกันไม่ให้ผู้ใช้ที่ยืนยันตัวตนแล้วเข้าถึงหน้าเหล่านั้น ## Rate Limiting ด้วย Throttle Middleware Laravel Middleware Rate Limiting ปกป้อง Route จากการถูกใช้งานเกินขอบเขตด้วย `throttle` Middleware ในตัว รูปแบบที่ง่ายที่สุดรับพารามิเตอร์สองตัว ได้แก่ จำนวน Request สูงสุดและกรอบเวลาเป็นนาที ```php // routes/api.php // Allow 60 requests per minute per user Route::middleware('throttle:60,1')->group(function () { Route::get('/posts', [PostController::class, 'index']); Route::get('/posts/{post}', [PostController::class, 'show']); }); // Stricter limit for write operations Route::middleware(['auth:sanctum', 'throttle:10,1'])->group(function () { Route::post('/posts', [PostController::class, 'store']); Route::put('/posts/{post}', [PostController::class, 'update']); }); ``` ### Named Rate Limiters สำหรับการควบคุมขั้นสูง การกำหนด Named Rate Limiters ใน `AppServiceProvider` จะให้การควบคุมที่ละเอียดยิ่งขึ้นตามบริบทของผู้ใช้ วิธีนี้มีความยืดหยุ่นมากกว่าการใช้พารามิเตอร์ Throttle แบบ Inline ```php // app/Providers/AppServiceProvider.php use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Support\Facades\RateLimiter; use Illuminate\Http\Request; public function boot(): void { // API rate limiter with tiered access RateLimiter::for('api', function (Request $request) { $user = $request->user(); if ($user?->hasSubscription('enterprise')) { return Limit::perMinute(500)->by($user->id); // Enterprise: 500/min } if ($user) { return Limit::perMinute(100)->by($user->id); // Authenticated: 100/min } return Limit::perMinute(20)->by($request->ip()); // Anonymous: 20/min }); // Login limiter to prevent brute force RateLimiter::for('login', function (Request $request) { return Limit::perMinute(5) ->by($request->ip()) // Key by IP address ->response(function () { // Custom exceeded response return response()->json([ 'message' => 'Too many login attempts. Try again in a minute.', ], 429); }); }); } ``` การนำ Named Limiters ไปใช้กับ Route จะใช้ Syntax `throttle:name` ดังนี้ ```php // routes/api.php Route::middleware('throttle:api')->group(function () { Route::apiResource('/posts', PostController::class); }); // routes/web.php Route::middleware('throttle:login') ->post('/login', [AuthController::class, 'login']); ``` Tiered Rate Limiter ข้างต้นเป็นรูปแบบที่ใช้จริงในโปรดักชัน โดยผู้ใช้ระดับ Enterprise จะได้รับ Limit ที่สูงกว่า ผู้ใช้ที่ยืนยันตัวตนแล้วจะได้รับ Limit ระดับปานกลาง และ Request จากผู้ใช้ที่ไม่ระบุตัวตนจะถูกจำกัดอย่างเข้มงวด เมธอด `by()` กำหนด Rate Limit Key โดยใช้ User ID สำหรับผู้ใช้ที่ยืนยันตัวตนแล้ว และ IP Address เป็นทางเลือกสำรอง ## การสร้าง Custom Middleware ตั้งแต่เริ่มต้น การสร้าง Custom Middleware ครอบคลุมสถานการณ์ที่ Built-in Middleware ไม่สามารถจัดการได้ คำสั่ง `make:middleware` ของ Artisan จะสร้าง Class ใหม่พร้อมโครงสร้างที่ถูกต้อง ```bash php artisan make:middleware EnsureUserHasRole ``` ### Role-Based Access Control Middleware รูปแบบ Custom Middleware ที่พบบ่อยคือการบังคับใช้ Role-Based Authorization ที่ระดับ Route โดยรับชื่อ Role เป็นพารามิเตอร์ ```php // app/Http/Middleware/EnsureUserHasRole.php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class EnsureUserHasRole { public function handle(Request $request, Closure $next, string ...$roles): Response { $user = $request->user(); if (! $user || ! $user->hasAnyRole($roles)) { abort(403, 'Insufficient permissions.'); } return $next($request); } } ``` พารามิเตอร์แบบ Variadic `...$roles` อนุญาตให้ส่ง Role หลายตัวคั่นด้วยเครื่องหมายจุลภาค การลงทะเบียนและการใช้งานมีลักษณะดังนี้ ```php // bootstrap/app.php ->withMiddleware(function (Middleware $middleware) { $middleware->alias([ 'role' => \App\Http\Middleware\EnsureUserHasRole::class, ]); }) // routes/web.php Route::middleware('role:admin')->group(function () { Route::get('/admin', [AdminController::class, 'index']); }); // Multiple roles: admin OR editor can access Route::middleware('role:admin,editor')->group(function () { Route::resource('/articles', ArticleController::class); }); ``` ### Request Transformation Middleware Middleware สามารถแก้ไข Request ก่อนที่จะถึง Controller ตัวอย่างเช่น JSON API Middleware ที่บังคับใช้ Content Type Header และตัดช่องว่างจาก String Input ```php // app/Http/Middleware/ApiRequestSanitizer.php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class ApiRequestSanitizer { public function handle(Request $request, Closure $next): Response { // Reject non-JSON requests on API routes if (! $request->expectsJson() && $request->isMethod('POST')) { return response()->json( ['error' => 'Content-Type must be application/json'], 415 ); } // Trim all string inputs $input = $request->all(); array_walk_recursive($input, function (&$value) { if (is_string($value)) { $value = trim($value); } }); $request->merge($input); return $next($request); } } ``` Middleware ตัวนี้จัดการสองเรื่องพร้อมกัน ได้แก่ การตรวจสอบ Content Type สำหรับ POST Request และการทำความสะอาด String Input ทั้งหมดด้วยการตัดช่องว่าง ## การลงทะเบียน Middleware ใน Laravel 12 Laravel 12 รวมศูนย์การลงทะเบียน Middleware ทั้งหมดไว้ใน `bootstrap/app.php` ซึ่งมาแทนที่แนวทาง `app/Http/Kernel.php` แบบเดิมที่ใช้ก่อน Laravel 11 ```php // bootstrap/app.php use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Middleware; return Application::configure(basePath: dirname(__DIR__)) ->withMiddleware(function (Middleware $middleware) { // Global middleware (runs on every request) $middleware->append( \App\Http\Middleware\LogRequestTime::class ); // Add to the 'web' middleware group $middleware->web(append: [ \App\Http\Middleware\TrackPageViews::class, ]); // Add to the 'api' middleware group $middleware->api(prepend: [ \App\Http\Middleware\ApiRequestSanitizer::class, ]); // Register aliases for route-level use $middleware->alias([ 'role' => \App\Http\Middleware\EnsureUserHasRole::class, 'subscribed' => \App\Http\Middleware\EnsureUserIsSubscribed::class, ]); // Control execution order $middleware->priority([ \Illuminate\Session\Middleware\StartSession::class, \Illuminate\Auth\Middleware\Authenticate::class, \App\Http\Middleware\EnsureUserHasRole::class, ]); }) ->create(); ``` Array `priority` มีความสำคัญเมื่อ Middleware หลายตัวถูกกำหนดให้กับ Route เดียวกัน Laravel จะเรียงลำดับการทำงานตามรายการนี้ เพื่อให้มั่นใจว่า Session จะเริ่มทำงานก่อน Authentication และ Authentication จะเสร็จสิ้นก่อนการตรวจสอบ Role > **ลำดับการทำงานของ Middleware** > > Middleware ทำงานตามลำดับที่ลงทะเบียนไว้ สำหรับ Middleware ระดับ Route นั้น Array `priority` จะ Override ลำดับเริ่มต้น ควรวาง Authentication Middleware ไว้ก่อน Authorization Middleware เสมอ เพื่อหลีกเลี่ยงการตรวจสอบ Role กับ Request ที่ยังไม่ได้ยืนยันตัวตน ## Terminable Middleware สำหรับงานหลังส่ง Response Terminable Middleware จะดำเนินการตรรกะ **หลัง** จากที่ Response ถูกส่งไปยังผู้ใช้แล้ว สิ่งนี้มีประโยชน์สำหรับการบันทึก Log, Analytics หรืองาน Cleanup ที่ไม่ควรบล็อกการตอบสนองต่อผู้ใช้ ```php // app/Http/Middleware/CollectAnalytics.php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Symfony\Component\HttpFoundation\Response; class CollectAnalytics { public function handle(Request $request, Closure $next): Response { return $next($request); // Pass through without delay } public function terminate(Request $request, Response $response): void { // Runs after response is sent to client DB::table('analytics')->insert([ 'path' => $request->path(), 'method' => $request->method(), 'status_code' => $response->getStatusCode(), 'user_id' => $request->user()?->id, 'ip' => $request->ip(), 'created_at' => now(), ]); } } ``` เมธอด `terminate` จะรับทั้ง Request เดิมและ Response สุดท้าย ควรลงทะเบียน Middleware นี้เป็น Singleton ใน `AppServiceProvider` เพื่อให้มั่นใจว่า Instance เดียวกันจะจัดการทั้งเมธอด `handle()` และ `terminate()` ## รูปแบบ Middleware สำหรับใช้งานจริงในโปรดักชัน มีรูปแบบ Middleware หลายรูปแบบที่ปรากฏอย่างสม่ำเสมอใน Laravel Application ที่ใช้งานจริงในโปรดักชัน **Maintenance Mode Bypass** อนุญาตให้ IP ภายในเข้าถึง Application ในระหว่างการบำรุงรักษา ```php // app/Http/Middleware/MaintenanceBypass.php class MaintenanceBypass { private array $allowedIps = ['192.168.1.0/24', '10.0.0.1']; public function handle(Request $request, Closure $next): Response { if (app()->isDownForMaintenance()) { foreach ($this->allowedIps as $ip) { if ($request->ip() === $ip) { return $next($request); } } } return $next($request); } } ``` **Security Headers** เพิ่ม HSTS, Content Security Policy และ Header อื่น ๆ ในทุก Response ```php // app/Http/Middleware/SecurityHeaders.php class SecurityHeaders { public function handle(Request $request, Closure $next): Response { $response = $next($request); $response->headers->set('X-Content-Type-Options', 'nosniff'); $response->headers->set('X-Frame-Options', 'SAMEORIGIN'); $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin'); $response->headers->set( 'Strict-Transport-Security', 'max-age=31536000; includeSubDomains' ); return $response; } } ``` รูปแบบเหล่านี้แสดงให้เห็นตำแหน่งหลักสองตำแหน่งของ Middleware ได้แก่ **ก่อน** Request (Maintenance Bypass ตรวจสอบ IP และอาจบล็อก) และ **หลัง** Response (Security Headers แก้ไข Response ที่ส่งออกไป) ## สรุป - Laravel Middleware ทำงานเป็น Pipeline โดยแต่ละ Class จะประมวลผล Request ดำเนินการกับมัน แล้วส่งต่อหรือตัดวงจรด้วยการคืน Response - `auth` Middleware ปกป้อง Route ด้วย Guard-Based Authentication รองรับผู้ใช้หลายประเภทผ่าน Syntax `auth:guard` - Rate Limiting ผ่าน `throttle` Middleware และการกำหนด Named `RateLimiter::for()` ช่วยให้สามารถควบคุมการเข้าถึงแบบแบ่งระดับตามบริบทของผู้ใช้ - Custom Middleware จัดการ Cross-Cutting Concerns เช่น การตรวจสอบ Role, การทำความสะอาด Request และ Security Headers โดยไม่ทำให้ Controller รกรุงรัง - การลงทะเบียน Middleware ทั้งหมดใน Laravel 12 ทำใน `bootstrap/app.php` ผ่าน Fluent API โดยใช้ `priority` ควบคุมลำดับการทำงาน - Terminable Middleware ทำงานหลังส่ง Response (Analytics, Logging) โดยไม่กระทบต่อ Latency ที่ผู้ใช้รับรู้ - พารามิเตอร์ของ Middleware ผ่าน Syntax `:param` ทำให้ Route Definition มีความชัดเจนและ Middleware Class สามารถนำกลับมาใช้ซ้ำได้ในบริบทที่แตกต่างกัน --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/th/blog/laravel/laravel-middleware-deep-dive