Belajar Laravel 13 #8: Penjaga Pintu (Middleware)
Heru Iryanto
Teacher, Content Creator and Full-Stack DeveloperDi akhir materi sebelumnya, kita menemukan celah keamanan yang sangat fatal.
Sebuah website e-commerce memiliki rute URL /admin/laporan-keuangan. Tentu halaman ini sifatnya sangat privat dan hanya boleh dilihat oleh Bos yang sudah memiliki Username/Password.
Tetapi apa yang terjadi jika ada pengunjung iseng yang belum Login, menebak-nebak URL tersebut, lalu mengetiknya di kotak Browser: localhost:8000/admin/laporan-keuangan?
Jika Anda tidak melindunginya, Hacker tersebut akan langsung masuk dan mencuri data Anda!
Di PHP Klasik, kita memblokirnya dengan mengetik baris penderitaan di awal setiap file:
session_start();
if(!isset($_SESSION['user'])) {
header("Location: login.php");
exit;
}
Bayangkan jika Anda punya 50 file Admin? Anda harus menempelkannya 50 kali!
1️⃣ Mengenal Sang Penjaga: Middleware
Di Laravel, Anda tidak perlu repot menempelkan skrip di setiap file. Kita meletakkan sebuah Satpam di dalam file pusat Rute kita (routes/web.php). Satpam ini bernama Middleware.
Tugas utama Middleware adalah mencegat (Intersepsi) langkah pengunjung tepat sebelum pengunjung tersebut berhasil masuk ke Controller (Pelayan).
Ada banyak Middleware sakti bawaan Laravel. Salah satu yang paling diandalkan adalah Middleware bermarga auth (Singkatan dari Authenticated / Orang yang sudah terdaftar).
2️⃣ Cara Menggembok Rute (Route Protection)
Buka kembali file routes/web.php.
Mari kita masukkan kembali route-route artikel yang hilang saat kita membuat Authentication kemarin. Beberapa route nanti akan kita kunci mutlak menggunakan middleware auth.
Kita cukup merantainya dengan anak panah ->middleware('auth').
use App\Http\Controllers\ArtikelController; // Panggil Marga Pelayan
// Rute ini BEBAS DIBUKA siapa saja
Route::get('/artikel', [ArtikelController::class, 'index'])->name('artikel.index');
// Rute ini TERGEMBOK! Hanya bisa diakses oleh Karyawan yang punya kunci (Sudah Login)
Route::get('/artikel/create', [ArtikelController::class, 'create'])->name('artikel.create')->middleware('auth');
Route::post('/artikel', [ArtikelController::class, 'store'])->name('artikel.store')->middleware('auth');
// Rute ini BEBAS DIBUKA siapa saja
Route::get('/artikel/{id}', [ArtikelController::class, 'show'])->name('artikel.show');
// Rute ini TERGEMBOK! Hanya bisa diakses oleh Karyawan yang punya kunci (Sudah Login)
Route::get('/artikel/{id}/edit', [ArtikelController::class, 'edit'])->name('artikel.edit')->middleware('auth');
Route::put('/artikel/{id}', [ArtikelController::class, 'update'])->name('artikel.update')->middleware('auth');
Route::delete('/artikel/{id}', [ArtikelController::class, 'destroy'])->name('artikel.destroy')->middleware('auth');
Route-route diatas, silakan letakkan diatas require __DIR__.'/auth.php';.
Bagaimana reaksi sang Satpam?
Jika pengunjung iseng (yang belum login) memaksa mengetik URL /artikel/create di browser-nya, Satpam auth akan mencekiknya, dan langsung menendangnya secara otomatis ke halaman /login. Gagal total usaha peretasan!
3️⃣ Menggembok Secara Massal (Route Group)
Ketika ada beberapa route yang menggunakan ->middleware('auth') berulang-ulang, ada cara yang lebih efisien untuk melakukannya. Kita bisa mengelompokkan route-route tersebut dan menerapkan middleware ke seluruh grup sekaligus. Hal ini membuat kode lebih rapi dan mudah dibaca.
Kumpulkan rute-rute tersebut ke dalam sebuah keranjang (Group), lalu letakkan 1 Satpam di depan pintu keranjang tersebut! Sehingga route sebelumnya akan menjadi seperti ini:
// Rute ini BEBAS DIBUKA siapa saja
Route::get('/artikel', [ArtikelController::class, 'index'])->name('artikel.index');
// Rute ini TERGEMBOK! Hanya bisa diakses oleh Karyawan yang punya kunci (Sudah Login)
Route::middleware(['auth'])->group(function () {
Route::get('/artikel/create', [ArtikelController::class, 'create'])->name('artikel.create');
Route::post('/artikel', [ArtikelController::class, 'store'])->name('artikel.store');
});
// Rute ini BEBAS DIBUKA siapa saja
Route::get('/artikel/{id}', [ArtikelController::class, 'show'])->name('artikel.show');
// Rute ini TERGEMBOK! Hanya bisa diakses oleh Karyawan yang punya kunci (Sudah Login)
Route::middleware(['auth'])->group(function () {
Route::get('/artikel/{id}/edit', [ArtikelController::class, 'edit'])->name('artikel.edit');
Route::put('/artikel/{id}', [ArtikelController::class, 'update'])->name('artikel.update');
Route::delete('/artikel/{id}', [ArtikelController::class, 'destroy'])->name('artikel.destroy');
});
Sangat elegan, efisien, dan bersih. Anda tidak akan pernah kebobolan akses dari Hacker yang belum login!
4️⃣ Custom Middleware (Fitur Lanjutan)
(Ini adalah ilmu sekadar tahu, biasa diajarkan di kelas Laravel tingkat Mahir).
Selain menggunakan auth bawaan Laravel, kita bisa memproduksi Satpam Kustom kita sendiri.
Misal Anda membuat Middleware HanyaBolehUmur18.
Tugas Satpam ini adalah mengecek tahun lahir pengunjung. Jika di bawah 18 tahun, Satpam menendangnya ke halaman Peringatan.
Di Laravel 13 yang mengusung Slim Skeleton, jika Anda membuat Custom Middleware ini, Anda tidak perlu lagi mendaftarkannya di file rumit Kernel.php seperti di zaman kuno. Anda mendaftarkannya dengan sangat cantik di satu pusat komando bootstrap/app.php.
Langkah-langkah untuk membuat middleware HanyaBolehUmur18 :
4.1 Membuat Middleware
php artisan make:middleware HanyaBolehUmur18
Maka akan terbentuk file HanyaBolehUmur18.php.
app/
└── Http/
└── Middleware/
└── HanyaBolehUmur18.php
Silakan buka file tersebut, dan masukkan kode if seperti ini :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class HanyaBolehUmur18
{
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
// Jika umur < 18 (dibawah umur), Tendang ke halaman 403 (Forbidden)
if (auth()->user()->umur < 18) {
abort(403, 'Maaf, hanya pengguna berusia minimal 18 tahun yang dapat mengakses halaman ini.');
}
// Jika lolos, biarkan masuk ke Controller
return $next($request);
}
}
Selain abort(), kamu juga bisa mengarahkannya ke halaman lain, misalnya:
return redirect('/cuti')->with('pesan', 'Maaf! Akses ke Halaman ini hanya untuk yang berusia 18 tahun ke atas.');
4.2 Mendaftarkan Middleware
Pada Laravel 11, 12, dan 13, middleware didaftarkan di bootstrap/app.php. Silakan buka file tersebut lalu tambahkan alias:
->withMiddleware(function (Middleware $middleware): void {
//ini adalah tempat untuk mendaftarkan Middleware baru yang kita buat, misalnya HanyaBolehUmur18
$middleware->alias([
'umur18' => \App\Http\Middleware\HanyaBolehUmur18::class,
]);
})
Sekarang middleware dapat dipanggil dengan nama umur18.
4.3 Menggunakan Middlewaare
Jika kita ingin menggunakan middleware yang baru kita buat, kita tinggal menaruhnya di route. Di web.php coba ubah route /artikel/create menjadi menggunakan middleware umur18:
Route::middleware(['auth','umur18'])->group(function () {
Route::get('/artikel/create', [ArtikelController::class, 'create'])->name('artikel.create');
Route::post('/artikel', [ArtikelController::class, 'store'])->name('artikel.store');
});
Sekarang coba tes di browser untuk mengakses halaman http://127.0.0.1:8000/artikel/create. Apa yang terjadi ? Anda akan ditendang ke halaman 403: Maaf, hanya pengguna berusia minimal 18 tahun yang dapat mengakses halaman ini. Itu karena kamu belum mempunyai field umur di tabel user atau jika sudah memiliki field umur tapi usianya dibawah 18.
🗽 Kesimpulan
Jika Anda telah mengamankan Rute menggunakan Middleware auth, 90% pilar arsitektur aplikasi Anda sudah layak untuk ditayangkan kepada klien bisnis di dunia nyata. Ditambah lagi kamu sudah mempelajari custom middleware.
Satu-satunya kepingan fitur krusial yang belum kita pelajari adalah kemampuan untuk mengunggah gambar/berkas (File Upload). Sistem penyimpanan file Laravel sangatlah kompleks dan aman. Mari bongkar rahasia penyimpanannya di materi Manajemen Berkas (File Storage).
