Laravel Middleware Deep Dive: Authentication, Rate Limiting, dan Custom Middleware

Panduan mendalam tentang Laravel middleware mencakup authentication, rate limiting, dan pembuatan custom middleware untuk aplikasi Laravel yang aman dan optimal di tahun 2026.

Panduan mendalam Laravel middleware mencakup authentication, rate limiting, dan custom middleware

Laravel middleware berperan sebagai lapisan penyaring antara request HTTP yang masuk dan logika aplikasi. Setiap request melewati rangkaian middleware sebelum mencapai controller, dan setiap response kembali melalui rangkaian yang sama. Pemahaman menyeluruh terhadap mekanisme ini sangat penting bagi pengembang yang ingin membangun aplikasi Laravel yang aman dan berperforma tinggi di tahun 2026.

Middleware Secara Ringkas

Middleware mencegat request HTTP sebelum mencapai route. Laravel 12 mendaftarkan seluruh middleware di bootstrap/app.php menggunakan fluent API. Middleware bawaan menangani authentication, proteksi CSRF, manajemen session, dan rate limiting secara langsung tanpa konfigurasi tambahan.

Cara Kerja Pipeline Middleware di Laravel

HTTP kernel Laravel memproses setiap request melalui tumpukan middleware. Masing-masing middleware menerima request, menjalankan logikanya, lalu meneruskan request ke lapisan berikutnya melalui $next($request) atau menghentikan pipeline dengan mengembalikan response secara langsung.

Arsitektur ini mengikuti pola Chain of Responsibility. Middleware dapat bertindak sebelum request mencapai controller (misalnya pemeriksaan authentication), setelah response dihasilkan (misalnya menambahkan header), atau keduanya sekaligus.

app/Http/Middleware/LogRequestTime.phpphp
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 di atas membungkus request: mencatat waktu mulai sebelum pemrosesan dan mencatat durasi setelah response kembali. Pola before/after ini merupakan inti dari cara kerja middleware.

Authentication Middleware: Melindungi Route

Laravel menyediakan middleware alias auth yang dipetakan ke Illuminate\Auth\Middleware\Authenticate. Menerapkannya pada sebuah route memastikan hanya pengguna yang telah terautentikasi yang dapat mengaksesnya. Pengguna yang belum login akan menerima response 401 (API) atau dialihkan ke halaman login (web).

routes/web.phpphp
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

Aplikasi yang memiliki beberapa tipe pengguna (panel admin, area pelanggan, API) memperoleh manfaat dari authentication berbasis guard. Middleware auth menerima parameter guard untuk menentukan driver authentication yang digunakan.

routes/api.phpphp
// 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']);
});

Parameter guard setelah tanda titik dua memberitahu Laravel konfigurasi authentication mana yang harus diverifikasi. Pendekatan ini menjaga logika authentication tetap bersih dan terpisah di berbagai bagian aplikasi.

Guest Middleware

Middleware guest merupakan kebalikan dari auth — hanya mengizinkan pengguna yang belum terautentikasi untuk melewatinya. Menerapkannya pada route login dan registrasi mencegah pengguna yang sudah login mengakses halaman tersebut.

Rate Limiting dengan Throttle Middleware

Rate limiting pada middleware Laravel melindungi route dari penyalahgunaan menggunakan middleware bawaan throttle. Bentuk paling sederhana menerima dua parameter: jumlah maksimum request dan jendela waktu dalam menit.

routes/api.phpphp
// 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 Limiter untuk Kontrol Lebih Lanjut

Mendefinisikan named rate limiter di AppServiceProvider memberikan kontrol yang lebih detail terhadap pembatasan berdasarkan konteks pengguna. Pendekatan ini jauh lebih fleksibel dibandingkan parameter throttle secara inline.

app/Providers/AppServiceProvider.phpphp
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);
            });
    });
}

Penerapan named limiter pada route menggunakan sintaks throttle:name:

routes/api.phpphp
Route::middleware('throttle:api')->group(function () {
    Route::apiResource('/posts', PostController::class);
});

// routes/web.php
Route::middleware('throttle:login')
    ->post('/login', [AuthController::class, 'login']);

Rate limiter bertingkat di atas menunjukkan pola yang umum digunakan di production: pengguna enterprise mendapatkan batas lebih tinggi, pengguna terautentikasi mendapatkan batas moderat, dan request anonim dibatasi secara agresif. Method by() menentukan kunci rate limit — menggunakan user ID untuk pengguna terautentikasi dan alamat IP sebagai fallback.

Siap menguasai wawancara Laravel Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Membuat Custom Middleware dari Awal

Pembuatan custom middleware mencakup skenario yang tidak ditangani oleh middleware bawaan. Perintah Artisan make:middleware menghasilkan class baru dengan struktur yang benar.

bash
php artisan make:middleware EnsureUserHasRole

Middleware untuk Kontrol Akses Berbasis Role

Salah satu pola custom middleware yang paling umum adalah menerapkan otorisasi berbasis role pada tingkat route, dengan menerima nama role sebagai parameter.

app/Http/Middleware/EnsureUserHasRole.phpphp
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);
    }
}

Parameter variadic ...$roles memungkinkan pengiriman beberapa role yang dipisahkan koma. Pendaftaran dan penggunaannya adalah sebagai berikut:

bootstrap/app.phpphp
->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);
});

Middleware untuk Transformasi Request

Middleware juga dapat memodifikasi request sebelum mencapai controller. Berikut contoh middleware JSON API yang memvalidasi header content type dan memangkas input string:

app/Http/Middleware/ApiRequestSanitizer.phpphp
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 ini menangani dua hal sekaligus: memvalidasi content type untuk request POST dan membersihkan seluruh input string dengan memangkas whitespace.

Pendaftaran Middleware di Laravel 12

Laravel 12 memusatkan seluruh pendaftaran middleware di bootstrap/app.php. Pendekatan ini menggantikan cara lama melalui app/Http/Kernel.php yang digunakan sebelum Laravel 11.

bootstrap/app.phpphp
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 sangat penting ketika beberapa middleware diterapkan pada route yang sama. Laravel mengurutkannya sesuai daftar ini, memastikan session dimulai sebelum authentication berjalan, dan authentication selesai sebelum pemeriksaan role dilakukan.

Urutan Eksekusi Middleware

Middleware berjalan sesuai urutan pendaftarannya. Untuk middleware tingkat route, array priority menggantikan urutan default. Selalu tempatkan middleware authentication sebelum middleware authorization untuk menghindari pemeriksaan role pada request yang belum terautentikasi.

Terminable Middleware untuk Tugas Pasca-Response

Terminable middleware menjalankan logika setelah response dikirimkan kepada klien. Hal ini sangat berguna untuk pencatatan log, analitik, atau tugas pembersihan yang tidak seharusnya menghambat pengguna.

app/Http/Middleware/CollectAnalytics.phpphp
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(),
        ]);
    }
}

Method terminate menerima baik request asli maupun response final. Daftarkan middleware ini sebagai singleton di AppServiceProvider untuk memastikan instance yang sama menangani handle() dan terminate().

Pola Middleware Praktis untuk Production

Beberapa pola middleware secara konsisten muncul dalam aplikasi Laravel di lingkungan production.

Bypass maintenance mode — mengizinkan IP internal untuk mengakses aplikasi selama masa pemeliharaan:

app/Http/Middleware/MaintenanceBypass.phpphp
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 — menambahkan HSTS, content security policy, dan header keamanan lainnya pada setiap response:

app/Http/Middleware/SecurityHeaders.phpphp
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;
    }
}

Pola-pola ini menunjukkan dua posisi utama middleware: sebelum request (bypass maintenance memeriksa IP dan berpotensi memblokir) dan setelah response (security headers memodifikasi response yang keluar).

Siap menguasai wawancara Laravel Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Kesimpulan

  • Middleware Laravel beroperasi sebagai pipeline: setiap class memproses request, menjalankan aksinya, lalu meneruskannya atau menghentikan pipeline dengan mengembalikan response
  • Middleware auth melindungi route dengan authentication berbasis guard, mendukung beberapa tipe pengguna melalui sintaks auth:guard
  • Rate limiting melalui middleware throttle dan definisi RateLimiter::for() memungkinkan kontrol akses bertingkat berdasarkan konteks pengguna
  • Custom middleware menangani cross-cutting concern seperti pemeriksaan role, sanitasi request, dan security header tanpa mengotori controller
  • Seluruh pendaftaran middleware di Laravel 12 dilakukan di bootstrap/app.php menggunakan fluent API, dengan priority yang mengontrol urutan eksekusi
  • Terminable middleware menjalankan tugas pasca-response (analitik, logging) tanpa memengaruhi latensi yang dirasakan pengguna
  • Parameter middleware melalui sintaks :param menjaga definisi route tetap ekspresif dan class middleware dapat digunakan kembali di berbagai konteks

Mulai berlatih!

Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

Tag

#laravel
#middleware
#authentication
#rate-limiting
#php

Bagikan

Artikel terkait