Bikin Login Next.js Aman dari Brute Force, Gak Pake Ribet!
Pernah Gak Sih Server Lo Dihajar Bot?
Pernah gak lo lagi asik-asik ngopi sambil mantau dashboard, eh tiba-tiba log server lo penuh sama percobaan login yang aneh-aneh? Username-nya 'admin', password-nya '123456', terus berulang ribuan kali tiap detiknya. Kalo lo pernah ngalamin ini, selamat! Web lo lagi kena serangan Brute Force. Rasanya tuh kayak ada orang asing yang nyoba nendang pintu rumah lo berkali-kali pake ribuan kunci cadangan sampe pintunya jebol atau engselnya copot.
Masalahnya, banyak developer pemula yang mikir, 'Ah, kan udah pake password rumit, aman lah!'. Padahal bukan cuma soal password jebol, lur. Serangan kayak gini bisa bikin server lo mager alias lemot parah karena sibuk ngelayanin request sampah dari bot. Makanya, kita butuh yang namanya Rate Limiting. Tapi tenang, kita gak bakal install library raksasa yang bikin ukuran node_modules makin bengkak. Kita bakal bikin sendiri pake cara yang sat-set-wat-wet!
Kenapa Gak Pake Library Aja?
Sebenernya banyak sih library kayak express-rate-limit atau sejenisnya. Tapi di Next.js, apalagi kalo lo deploy di Vercel yang sifatnya serverless, library tradisional kayak gitu seringkali gak jalan maksimal karena tiap request bisa aja lari ke instance yang beda. Selain itu, makin dikit library, makin enteng aplikasi lo. Kita pengen yang lean, efisien, tapi tetep gaskeun buat urusan keamanan.
Konsep Dasar: Rate Limiting Sederhana
Intinya tuh gini: Kita bakal nyatet setiap IP yang nyoba login. Kalo IP si 'A' udah nyoba 5 kali dalam 1 menit dan semuanya gagal, ya udah, kita blokir dulu aksesnya buat beberapa menit ke depan. Simpel kan? Kayak satpam komplek yang curiga liat orang bolak-balik depan pager rumah lo.
Langkah 1: Bikin Helper Rate Limiter
Karena kita main di Next.js (App Router atau Pages Router sama aja konsepnya), kita butuh tempat buat nyimpen data percobaan login. Kalo buat skala kecil atau lokal, kita bisa pake Map di memory. Tapi inget, kalo di serverless, memory ini bakal di-reset tiap kali fungsi 'dingin' (cold start). Tapi buat belajar, yuk kita bikin versi dasarnya dulu.
// lib/rate-limit.ts
const tracker = new Map();
export const rateLimit = (ip: string) => {
const now = Date.now();
const windowMs = 60 * 1000; // 1 menit
const maxAttempts = 5;
const record = tracker.get(ip) || { count: 0, startTime: now };
if (now - record.startTime > windowMs) {
record.count = 1;
record.startTime = now;
} else {
record.count++;
}
tracker.set(ip, record);
return {
isBlocked: record.count > maxAttempts,
remaining: Math.max(0, maxAttempts - record.count),
};
};Penjelasan Kodenya, Lur
Di atas, kita bikin Map buat nyimpen data IP. Tiap ada request masuk, kita cek udah berapa kali IP itu 'getok' pintu login kita. Kalo udah lewat dari maxAttempts (5 kali), kita kasih status isBlocked: true. Wkwk, mampus deh tuh bot gak bisa masuk!
Langkah 2: Implementasi di API Login
Sekarang tinggal kita pasang di route login kita. Misal lo pake App Router di app/api/login/route.ts. Kita panggil helper tadi sebelum ngecek database. Jadi kalo emang udah diblokir, kita gak usah repot-repot nanya ke database, hemat resource kan?
import { NextResponse } from 'next/server';
import { rateLimit } from '@/lib/rate-limit';
export async function POST(request: Request) {
const ip = request.headers.get('x-forwarded-for') || 'anonymous';
const limit = rateLimit(ip);
if (limit.isBlocked) {
return NextResponse.json(
{ error: 'Terlalu banyak percobaan! Mager ah, coba lagi nanti ya.' },
{ status: 429 }
);
}
const { username, password } = await request.json();
// Di sini logika cek password lo (misal ke Prisma atau Supabase)
const isValid = username === 'admin' && password === 'rahasia';
if (!isValid) {
return NextResponse.json(
{ error: 'Password salah, lur!', remaining: limit.remaining },
{ status: 401 }
);
}
return NextResponse.json({ message: 'Login sukses! Gaskeun!' });
}Masalah Serverless (Vercel/Netlify)
Kalo lo deploy ke Vercel, variabel tracker di atas itu bakal sering ilang karena serverless function itu sifatnya stateless. Solusinya gimana? Pake Redis. Tenang, ada yang gratisan kayak Upstash. Konsepnya sama, cuma datanya gak disimpen di memory server, tapi di database Redis yang super kenceng. Jadi biarpun server lo mati-nyala, catatan 'dosa' si penyerang tetep kesimpen.
Kenapa Harus Redis?
Redis itu kayak buku catetan satpam yang ditaruh di pos penjagaan pusat. Siapa pun satpam yang jaga (instance server mana pun), mereka baca buku yang sama. Jadi gak ada celah buat bot buat 'nipu' sistem kita cuma dengan pindah instance. Mantap banget kan?
Tips Tambahan Biar Makin Kebal
Selain rate limiting, ada beberapa hal lagi yang bisa lo lakuin biar sistem login lo makin kayak benteng:
- Gunakan Captcha: Kalo udah gagal 3 kali, munculin Google reCAPTCHA atau Cloudflare Turnstile. Bot biasanya langsung nyerah kalo disuruh milih gambar lampu lalu lintas.
- Delay Response: Kasih
setTimeoutsengaja pas login gagal. Biar bot-nya nunggu lama tiap kali nyoba. - Notifikasi Email: Kalo ada percobaan login mencurigakan, kirim email ke user. 'Eh, ini lo bukan yang nyoba login dari Zimbabwe?'.
Intinya Sih...
Keamanan itu bukan soal sekali pasang terus ditinggal tidur. Brute force itu serangan paling klasik tapi tetep ampuh kalo kita teledor. Dengan modal beberapa baris kode tadi, lo udah bikin web Next.js lo jauh lebih aman dan gak gampang tumbang. Gak perlu library berat kalau logika dasar aja udah cukup, ya gak? Lagian, jadi developer itu harus kreatif manfaatin resource yang ada.
Gimana? Masih mau biarin form login lo 'telanjang' tanpa proteksi, atau mau langsung eksekusi tutorial ini sekarang juga?
FAQ (Pertanyaan Umum)
Q: Bang, kalo IP-nya ganti-ganti gimana?
A: Nah itu namanya Distributed Brute Force. Kalo udah level itu, mending pake Cloudflare WAF. Tapi buat bot receh, proteksi IP udah cukup kok.
Q: Aman gak simpen data di memory (Map)?
A: Buat traffic kecil sih oke aja, tapi kalo udah rame atau pake serverless, mending pindah ke Redis biar datanya gak gampang ilang pas cold start.
Q: Bikin lemot gak sih proses cek IP ini?
A: Gak lah, cek Map atau Redis itu itungannya milidetik. Jauh lebih cepet daripada ngebiarin bot nge-spam database lo sampe jebol.
Komentar (0)
Tinggalkan Jejak