Belajar Laravel #9: Middleware — Petugas Keamanan di Lorong Request

Seri Laravel ini sudah sampai episode ke-9, dan saya merasa sudah cukup nyaman dengan routing, controller, Blade, migration, Eloquent, dan form handling. Sekarang saatnya memahami satu lapisan lagi yang selama ini saya lihat tapi tidak terlalu pahami: middleware. Kalau routing itu penjaga pintu masuk dan controller itu yang menerima tamu, maka middleware itu semacam petugas keamanan di lorong sebelum tamu sampai ke ruangan. Dia bisa memeriksa tiket, memverifikasi identitas, atau bahkan memutar balik tamu yang tidak diundang — sebelum controller sempat melihat siapa yang datang.

Diagram alur request melewati middleware auth, verified, throttle sebelum sampai ke controller
Alur request melewati pipeline middleware sebelum sampai ke controller.

Apa itu middleware dan kenapa penting?

Middleware adalah lapisan kode yang menangani request sebelum sampai ke controller dan/atau response sebelum dikirim ke client. Analogi sederhananya: ketika kita masuk gedung perkantoran, ada satpam di lobby (cek KTP), ada resepsionis di lantai tujuan (arahkan ke ruangan yang tepat), dan ada lagi satpam di pintu keluar (pastikan tidak bawa barang kantor). Middleware bekerja persis seperti itu — satu per satu memeriksa request melalui pipeline.

Bayangkan sebuah aplikasi toko online. Request dari user bisa bermacam-macam: ada yang hanya melihat produk (umum), ada yang login untuk lihat riwayat belanja (perlu auth), ada yang jadi admin untuk mengatur stok (perlu role admin), dan ada yang coba menyerang CSRF atau SQL injection. Setiap jenis request ini butuh perlakuan berbeda. Daripada menulis pengecekan di setiap controller satu per satu, middleware memungkinkan kita mengelompokkan perlakuan itu dalam satu tempat yang bisa dipakai ulang.

Middleware bawaan Laravel

Laravel sudah menyediakan beberapa middleware yang siap pakai. Ini yang saya pelajari pertama kali karena paling sering dipakai:

NamaFungsiKapan dipakai
authMemastikan user sudah loginHalaman yang butuh autentikasi
guestMemastikan user BELUM loginHalaman login/register
verifiedMengecek email sudah diverifikasiSetelah user aktifkan akun
throttle:60,1Membatasi 60 request per menitLogin, API endpoints
signedMemverifikasi URL signatureLink akses via email

Middleware auth adalah yang paling sering saya pakai. Tanpa middleware ini, siapa saja bisa mengakses halaman profil, riwayat belanja, atau panel admin. Cukup tambahkan di route atau route group:

<?php
// routes/web.php

// Route yang butuh login
Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware('auth');

// Route untuk tamu saja (belum login)
Route::get('/login', [AuthController::class, 'showLogin'])
    ->middleware('guest');

// Route group — semua route di dalamnya pakai auth
Route::middleware('auth')->group(function () {
    Route::get('/profile', [ProfileController::class, 'index']);
    Route::get('/orders', [OrderController::class, 'index']);
    Route::post('/orders', [OrderController::class, 'store']);
});

Perhatikan ada dua cara pakai middleware: per route (satu-satu) atau route group (sekali untuk banyak route). Untuk aplikasi yang punya banyak halaman yang butuh login, pakai route group jauh lebih rapi daripada menambahkan ->middleware('auth') di setiap route.

Middleware pipeline: bagaimana request melewati middleware

Yang menarik dari middleware Laravel adalah konsep pipeline. Request tidak melompat langsung dari route ke controller. Request melewati serangkaian middleware secara berurutan, seperti air yang melewati beberapa saringan. Kalau satu saringan menolak (misalnya user belum login di middleware auth), request tidak pernah sampai ke controller — langsung dikembalikan dengan response penolakan (redirect ke login, atau response 401/403).

Ini bagus karena controller jadi lebih bersih. Controller tidak perlu lagi menulis if (!Auth::check()) return redirect('/login'); di awal setiap method. Cukup pasang middleware auth, dan Laravel menangani pengecekan untuk kita. Controller bisa fokus pada logika bisnis, bukan keamanan.

Membuat middleware custom

Ada kalanya middleware bawaan tidak cukup. Misalnya saya ingin membatasi akses hanya untuk admin saja — ini bukan sekadar cek login (sudah ditangani auth), tapi juga cek role. Laravel memungkinkan kita membuat middleware sendiri melalui Artisan:

php artisan make:middleware CheckAdminRole

Perintah ini membuat file baru di app/Http/Middleware/CheckAdminRole.php. Isinya kurang lebih seperti ini:

<?php
// app/Http/Middleware/CheckAdminRole.php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckAdminRole
{
    public function handle(Request $request, Closure $next)
    {
        // Cek apakah user sudah login dan role-nya admin
        if (!auth()->check() || auth()->user()->role !== 'admin') {
            return redirect()->route('home')
                ->with('error', 'Anda tidak memiliki akses.');
        }

        // Kalau lolos, teruskan ke middleware berikutnya / controller
        return $next($request);
    }
}

Perhatikan method handle. Method ini adalah jantung dari setiap middleware. Parameter $next adalah representasi middleware berikutnya di pipeline. Kalau kita panggil $next($request), request diteruskan. Kalau kita tidak memanggilnya dan langsung return response lain (redirect, error), maka request berhenti di situ — tidak sampai ke controller.

Agar middleware bisa dipakai, kita perlu mendaftarkannya di app/Http/Kernel.php (untuk Laravel 10 dan sebelumnya) atau di bootstrap/app.php (Laravel 11+). Berikut contoh pendaftaran di Laravel 10:

<?php
// app/Http/Kernel.php — Laravel 10

protected $middlewareAliases = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'admin' => \App\Http\Middleware\CheckAdminRole::class,  // <- tambah di sini
];

Sekarang saya bisa pakai middleware admin di route:

<?php
Route::middleware(['auth', 'admin'])->group(function () {
    Route::get('/admin/dashboard', [AdminDashboard::class, 'index']);
    Route::get('/admin/products', [AdminProductController::class, 'index']);
    Route::post('/admin/products', [AdminProductController::class, 'store']);
});

Perhatikan urutan: auth dulu, baru admin. Ini penting — middleware dijalankan sesuai urutan pendaftaran. Kalau admin dijalankan sebelum auth, maka auth()->user() akan kosong karena user belum diproses oleh middleware auth. Urutan pipeline ini mirip seperti tumpukan filter dalam sebuah prosesor: request masuk dari luar (pertama kali) dan keluar dari sisi dalam.

Middleware untuk throttling (anti brute force)

Satu lagi middleware yang sangat penting untuk keamanan: throttle. Middleware ini membatasi jumlah request dari satu IP dalam periode waktu tertentu. Ini sangat berguna untuk halaman login — kalau ada orang yang mencoba menebak password dengan brute force (ratusan percobaan login per detik), throttle akan memblokirnya setelah beberapa percobaan gagal.

<?php
// Limit: 5 percobaan login per 1 menit
Route::post('/login', [AuthController::class, 'login'])
    ->middleware('throttle:5,1');

// Atau pakai named limiter (lebih fleksibel)
Route::post('/login', [AuthController::class, 'login'])
    ->middleware('throttle:login');

Jika pakai named limiter, konfigurasinya ada di app/Providers/RouteServiceProvider.php (Laravel 10) atau bootstrap/app.php (Laravel 11+). Laravel 11 menggunakan sistem rate limiter yang sudah lebih terintegrasi — cukup panggil RateLimiter::for() untuk mendefinisikan limiter kustom. Ini lebih fleksibel daripada hardcode angka di route, karena kita bisa menambahkan logika pengecekan email existence, logging percobaan gagal, atau bahkan mengirim notifikasi ke admin jika ada pola mencurigakan.

Middleware prioritas dan urutan

Satu hal yang sempat bikin saya bingung: bagaimana Laravel menentukan urutan middleware? Ternyata ada urutan global (dijalankan untuk semua request) yang didefinisikan di Kernel.php, lalu urutan route group, lalu urutan per-route. Ini seperti susunan filter yang berlapis — filter global paling luar, lalu filter group, lalu filter individu.

Beberapa prinsip yang saya pelajari terkait urutan middleware:

  • Middleware global ($middleware di Kernel) dijalankan untuk SEMUA request — hanya untuk hal yang benar-benar universal seperti Force HTTPS atau Trust Proxies.
  • Middleware grup dijalankan untuk semua route dalam group — cocok untuk autentikasi atau autorisasi.
  • Middleware per-route hanya dijalankan untuk route tertentu — cocok untuk kebutuhan spesifik seperti pengecekan role admin.
  • Middleware yang menolak request (tidak memanggil $next) akan menghentikan pipeline — request tidak sampai ke controller.

Kesimpulan

Middleware adalah salah satu fitur Laravel yang paling elegan — ia memisahkan urusan keamanan dan cross-cutting concerns dari logika bisnis di controller. Dari episode ini, saya belajar bahwa:

  1. Middleware adalah lapisan penanganan request di antara route dan controller, bekerja dalam pipeline berurutan.
  2. Laravel menyediakan middleware bawaan untuk autentikasi (auth), tamu (guest), verifikasi (verified), dan rate limiting (throttle).
  3. Middleware custom bisa dibuat dengan php artisan make:middleware, kemudian didaftarkan di Kernel.
  4. Urutan middleware berpengaruh — jalankan pengecekan auth dulu, baru autorisasi atau role.

Di episode selanjutnya, saya akan mendalami Authentication — scaffolding login/register, Breeze, hash password, dan konsep guard & provider. Middleware auth yang kita pakai di episode ini sebenarnya sudah mengarah ke sana, tapi ada lebih banyak detail di balik layar yang perlu dipahami.


Sumber

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

Situs ini menggunakan Akismet untuk mengurangi spam. Pelajari bagaimana data komentar Anda diproses