Form login yang “berfungsi” belum tentu aman. Implementasi yang sehat harus memikirkan password hashing, query parameter, session fixation, rate limiting, dan respons error.
Register: validasi lalu hash
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$password = (string) ($_POST['password'] ?? '');
if (!$email || strlen($password) < 12) {
throw new InvalidArgumentException('Data registrasi tidak valid.');
}
$hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare(
'INSERT INTO users (email, password_hash) VALUES (:email, :hash)'
);
$stmt->execute(['email' => $email, 'hash' => $hash]);Jangan mengenkripsi password dengan algoritma reversible dan jangan membuat salt sendiri. password_hash() menyimpan parameter yang diperlukan langsung di hash.
Login tanpa membocorkan akun
$stmt = $pdo->prepare(
'SELECT id, password_hash FROM users WHERE email = :email LIMIT 1'
);
$stmt->execute(['email' => $email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
$valid = $user && password_verify($password, $user['password_hash']);
if (!$valid) {
// Pesan sama untuk email tidak ada maupun password salah.
throw new RuntimeException('Email atau password tidak sesuai.');
}
session_regenerate_id(true);
$_SESSION['user_id'] = (int) $user['id'];Konfigurasi session
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();Rate limiting sederhana
Batasi percobaan berdasarkan kombinasi akun dan sinyal jaringan. Jangan hanya memblokir IP karena banyak pengguna dapat berada di jaringan yang sama. Untuk aplikasi kecil, simpan counter dengan masa berlaku; untuk skala besar, Redis lebih cocok.
| Kontrol | Tujuan |
|---|---|
| Password minimal 12 karakter | Mengurangi password mudah ditebak. |
| Generic error message | Mencegah enumerasi akun. |
| Regenerate session ID | Mencegah session fixation. |
| CSRF token | Melindungi form perubahan state. |
| Audit log | Mendeteksi aktivitas tidak wajar. |
| MFA opsional/berisiko tinggi | Menambah lapisan verifikasi. |
Logout harus menghapus data session di server dan cookie di browser. Setelah itu, arahkan pengguna ke halaman publik dan jangan menyimpan data sensitif di cache browser.
