Mengamankan Aplikasi Laravel 11: Checklist Sebelum Go-Live

Laravel sudah membawa banyak perlindungan bawaan: token CSRF, password ter-hash, cookie terenkripsi, dan query yang memakai binding. Karena itu banyak developer merasa aplikasinya...

Mengamankan Aplikasi Laravel 11: Checklist Sebelum Go-Live

Laravel sudah membawa banyak perlindungan bawaan: token CSRF, password ter-hash, cookie terenkripsi, dan query yang memakai binding. Karena itu banyak developer merasa aplikasinya otomatis aman. Kenyataannya, sebagian besar insiden pada aplikasi Laravel justru terjadi karena konfigurasi produksi yang keliru atau fitur bawaan yang tidak dipakai dengan benar, misalnya file .env yang bisa diunduh siapa saja atau halaman edit invoice yang bisa dibuka pengguna lain hanya dengan mengganti angka di URL.

Artikel ini adalah checklist praktis untuk aplikasi Laravel 11 yang akan atau sudah berjalan di produksi. Setiap poin disertai cara mengeceknya, sehingga bisa langsung dipakai sebelum go-live atau saat mengaudit source code yang baru dibeli.

1. Konfigurasi Produksi: APP_DEBUG, APP_KEY, dan Lokasi .env

Tiga baris di .env ini paling sering menjadi sumber kebocoran:

APP_ENV=production
APP_DEBUG=false
APP_KEY=base64:... # dibuat dengan php artisan key:generate, jangan disalin dari proyek lain

Dengan APP_DEBUG=true, setiap error menampilkan stack trace, potongan kode, dan kadang isi variabel lingkungan seperti password database. APP_KEY dipakai untuk mengenkripsi cookie dan session; jika bocor atau dipakai bersama proyek lain, data terenkripsi bisa dibaca pihak lain.

Yang tidak kalah penting: document root web server harus mengarah ke folder public/, bukan ke root proyek. Jika salah, file .env, composer.json, bahkan folder storage/logs bisa diakses lewat browser. Cek dari komputer Anda:

curl -s -o /dev/null -w "%{http_code}\n" https://domainanda.com/.env
curl -s -o /dev/null -w "%{http_code}\n" https://domainanda.com/storage/logs/laravel.log

Keduanya harus menghasilkan 404 atau 403, bukan 200. Di shared hosting yang tidak bisa mengubah document root, ikuti langkah di panduan deploy Laravel ke shared hosting.

2. HTTPS dan Cookie yang Aman

Setelah sertifikat SSL terpasang, paksa semua URL memakai HTTPS dan pastikan cookie session hanya dikirim lewat koneksi terenkripsi:

# .env
APP_URL=https://domainanda.com
SESSION_SECURE_COOKIE=true
// app/Providers/AppServiceProvider.php
public function boot(): void
{
    if ($this->app->environment('production')) {
        \Illuminate\Support\Facades\URL::forceScheme('https');
    }
}

3. Mass Assignment: Tentukan Kolom yang Boleh Diisi

Kode User::create($request->all()) terlihat praktis, tetapi jika model tidak membatasi kolom, penyerang bisa menambahkan field is_admin=1 atau saldo=99999999 ke form. Selalu definisikan $fillable dan isi model dari data yang sudah divalidasi:

class User extends Authenticatable
{
    protected $fillable = ['name', 'email', 'password'];
}

// Controller
$data = $request->validate([
    'name'     => ['required', 'string', 'max:100'],
    'email'    => ['required', 'email', 'unique:users'],
    'password' => ['required', 'min:8', 'confirmed'],
]);
User::create($data); // bukan $request->all()

4. Otorisasi: Cegah Pengguna Membuka Data Milik Orang Lain

Celah yang paling sering ditemukan pada aplikasi bisnis adalah IDOR (Insecure Direct Object Reference): pengguna yang sudah login bisa membuka /invoice/15/edit milik pelanggan lain hanya dengan mengganti angka. Middleware auth tidak cukup, karena ia hanya memastikan pengguna sudah login, bukan bahwa data itu miliknya. Gunakan Policy:

php artisan make:policy InvoicePolicy --model=Invoice
// app/Policies/InvoicePolicy.php
public function update(User $user, Invoice $invoice): bool
{
    return $invoice->user_id === $user->id;
}

// Controller (Laravel 11)
use Illuminate\Support\Facades\Gate;

public function edit(Invoice $invoice)
{
    Gate::authorize('update', $invoice); // otomatis 403 bila bukan pemiliknya
    return view('invoice.edit', compact('invoice'));
}

Untuk aplikasi dengan banyak peran (admin, kasir, gudang), kombinasikan Policy dengan paket peran seperti dijelaskan di artikel role dan permission dengan Spatie.

5. Batasi Percobaan Login (Rate Limiting)

Tanpa pembatasan, form login bisa ditebak ribuan kali per menit. Definisikan limiter di AppServiceProvider, lalu pasang di route login:

// app/Providers/AppServiceProvider.php
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

public function boot(): void
{
    RateLimiter::for('login', function (Request $request) {
        return Limit::perMinute(5)->by(strtolower($request->input('email')) . '|' . $request->ip());
    });
}

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

Setelah lima percobaan gagal dalam satu menit dari kombinasi email dan IP yang sama, Laravel membalas HTTP 429. Starter kit resmi seperti Breeze sudah menerapkan pola serupa; jika Anda membuat form login sendiri, langkah ini wajib ditambahkan manual.

6. Cegah XSS di Blade

Sintaks {{ $variabel }} di Blade otomatis meng-escape HTML, sehingga skrip yang disisipkan pengguna tampil sebagai teks biasa. Bahaya muncul ketika memakai {!! $variabel !!} untuk data yang berasal dari pengguna, misalnya catatan pelanggan atau nama produk. Gunakan {!! !!} hanya untuk HTML yang Anda tulis sendiri atau yang sudah dibersihkan dengan library sanitizer. Cari semua pemakaiannya dengan:

grep -rn "{!!" resources/views/

7. Upload File: Validasi Tipe dan Simpan di Luar Folder Publik

Fitur unggah bukti transfer atau foto produk adalah jalur favorit untuk menanam file PHP berbahaya. Terapkan tiga aturan: batasi tipe dan ukuran, biarkan Laravel membuat nama file acak, dan simpan file sensitif di disk privat.

$request->validate([
    'bukti' => ['required', 'file', 'mimes:jpg,jpeg,png,pdf', 'max:2048'], // 2 MB
]);

// Disk "local" Laravel 11 berada di storage/app/private, tidak bisa diakses langsung lewat URL
$path = $request->file('bukti')->store('bukti-transfer');

// Menampilkan file lewat controller yang memeriksa hak akses
public function bukti(Order $order)
{
    Gate::authorize('view', $order);
    return Storage::download($order->bukti_path);
}

Jangan pernah memakai nama file asli dari pengguna sebagai nama simpanan, dan jangan menyimpan unggahan pengguna di public/ tanpa validasi tipe.

8. Tambahkan Security Header

Beberapa header HTTP sederhana menutup serangan seperti clickjacking dan MIME sniffing. Buat middleware lalu daftarkan secara global:

// app/Http/Middleware/SecurityHeaders.php
public function handle(Request $request, Closure $next): Response
{
    $response = $next($request);
    $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
    $response->headers->set('X-Content-Type-Options', 'nosniff');
    $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
    return $response;
}

// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\App\Http\Middleware\SecurityHeaders::class);
})

9. Perbarui Dependency Secara Berkala

Celah keamanan juga datang dari paket pihak ketiga. Composer 2.4 ke atas punya perintah bawaan untuk mengecek paket yang punya laporan kerentanan:

composer audit

Jalankan sebelum setiap deploy. Jika ada temuan, perbarui paket terkait dengan composer update nama/paket, lalu jalankan test sebelum naik ke produksi.

10. Siapkan Log dan Backup

Keamanan juga berarti bisa pulih ketika terjadi masalah. Pastikan storage/logs tidak membengkak tanpa batas (pakai channel daily dengan LOG_DAILY_DAYS), catat kejadian penting seperti login gagal berulang, dan jadwalkan backup database otomatis yang disimpan di luar server aplikasi.

Tabel Checklist Sebelum Go-Live

AreaYang dicekCara cepat mengecek
KonfigurasiAPP_DEBUG=false, APP_KEY unikBuka URL yang tidak ada; tidak boleh muncul stack trace
Document rootMengarah ke public/curl ke /.env harus 404/403
HTTPSRedirect ke https, cookie secureBuka versi http://, harus berpindah ke https://
Mass assignmentSemua model punya $fillablegrep -rn "request()->all()\|\$request->all()" app/
OtorisasiData milik pengguna dilindungi PolicyLogin sebagai user A, buka ID milik user B: harus 403
LoginRate limit aktifCoba login salah 6 kali: harus 429
XSS{!! !!} tidak dipakai untuk input penggunagrep -rn "{!!" resources/views/
UploadValidasi mimes dan max, disimpan privatCoba unggah file .php: harus ditolak
DependencyTidak ada paket rentancomposer audit

Kesalahan yang Sering Terjadi

  • Mengandalkan menu yang disembunyikan. Menyembunyikan tombol "Hapus" untuk kasir tidak mencegah kasir memanggil URL hapus secara langsung. Pengecekan hak akses harus ada di server.
  • Menyalin .env dari lokal ke produksi. Akibatnya APP_DEBUG masih true dan APP_KEY sama dengan mesin developer.
  • Membiarkan route debug atau tool development aktif. Pastikan paket seperti debugbar hanya dipasang sebagai require-dev dan produksi diinstal dengan composer install --no-dev.

Sebagian besar poin di atas hanya butuh beberapa menit, tetapi menutup celah yang paling sering dieksploitasi. Lanjutkan dengan membaca panduan mencegah SQL injection untuk memastikan lapisan database juga aman, dan cara kerja middleware Laravel jika ingin memahami di mana pengecekan keamanan dijalankan.

Ingin langsung mempraktikkannya?

Buat akun gratis untuk mengunduh contoh aplikasi Laravel, menyimpan tutorial favorit, dan mencoba kursus. Gratis, bisa daftar dengan akun Google.

Daftar Gratis Lihat katalog aplikasi
Yudhi
Ditulis oleh
Yudhi
Founder & Lead Developer, GudangCode

Yudhi adalah founder GudangCode dan developer Laravel dengan pengalaman membangun puluhan sistem informasi bisnis siap pakai — mulai dari POS, HRIS, hingga aplikasi manajemen. Ia menulis panduan dan artikel di GudangCode untuk membantu developer Indonesia menjalankan, memahami, dan men-deploy source code Laravel dengan benar.

Laravel PHP MySQL Sistem Informasi Bisnis
Lihat semua artikel Yudhi
Keamanan Laravel Keamanan & Best Practice
Bacaan Paling Dicari
📚 Free Learning Hub

Learn Coding for Free at DhieCoderWeb

Explore Laravel, PHP, JavaScript tutorials, source code, web development guides, and practical programming tips.

DhieCoderWeb
100+
Tutorials
Free
Learning
SEO
Tips
Visit Dhiecoderweb.com →