Proyek: Login Sederhana
Proyek akhir: sistem login + halaman admin + proteksi + logout yang aman.
Kenapa Proyek Ini?
Login adalah fitur paling diminta di web dan paling sering dibobol. Proyek akhir ini merangkai: form, validasi, password_hash/password_verify, session, session fixation protection, guard halaman, dan logout total. Selesai proyek ini, kamu punya template login aman yang bisa dipakai ulang di semua project.
<?php
// Contoh 1: struktur multi-file yang rapi
// config.php -> daftar user (nanti diganti database)
// auth.php -> fungsi guard + mulai session
// login.php -> form + proses
// dashboard.php -> halaman privat
// logout.php -> keluar total
// --- auth.php ---
session_start();
function wajibLogin(): void {
if (!isset($_SESSION["user_id"])) {
header("Location: login.php");
exit;
}
}
function sudahLogin(): bool {
return isset($_SESSION["user_id"]);
}
// --- config.php ---
$users = [
// username => [id, hash, nama]
"sinta" => ["id" => 1, "hash" => password_hash("sinta123", PASSWORD_DEFAULT), "nama" => "Sinta"],
];Memisahkan auth.php membuat guard konsisten: setiap halaman privat cukup require "auth.php"; wajibLogin();. Satu tempat untuk semua aturan keamanan session.
<?php
// Contoh 2: proses login + dashboard + logout
// --- login.php ---
require "auth.php";
if (sudahLogin()) { header("Location: dashboard.php"); exit; }
$error = "";
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$u = trim($_POST["username"] ?? "");
$p = $_POST["password"] ?? "";
require "config.php";
if (isset($users[$u]) && password_verify($p, $users[$u]["hash"])) {
session_regenerate_id(true);
$_SESSION["user_id"] = $users[$u]["id"];
$_SESSION["nama"] = $users[$u]["nama"];
header("Location: dashboard.php");
exit;
}
// Pesan generik: jangan bocorkan username mana yang salah!
$error = "Username atau password salah.";
}
// --- dashboard.php ---
require "auth.php";
wajibLogin();
echo "Halo, " . htmlspecialchars($_SESSION["nama"]);
// --- logout.php ---
require "auth.php";
$_SESSION = [];
setcookie(session_name(), "", time() - 3600, "/");
session_destroy();
header("Location: login.php");
exit;Pesan error login selalu generik ("username atau password salah"), tidak pernah "username tidak ditemukan": memberi tahu username mana yang valid membantu penyerang menebak akun.
Jebakan yang Sering Terjadi
Brute force tanpa batas. Tanpa rate limiting, penyerang bisa mencoba ribuan password per menit. Tambahkan jeda: catat waktu/gagal login per IP di session atau file, tolak setelah 5 gagal dalam 5 menit. Di production, ini wajib.
Session tidak pernah kedaluwarsa. Session default hidup sampai browser ditutup. Untuk keamanan, set batas idle: simpan $_SESSION["terakhir_aktif"] = time() tiap request, dan logout paksa jika lebih dari 30 menit tidak aktif. Modul session-keamanan membahas pola ini lengkap.
Peta Jalan Setelah Ini
Template login ini adalah fondasi. Urutan belajar yang disarankan setelahnya:
- Database: ganti array
$usersdengan tabel MySQL + prepared statement (modul database di track lanjutan). - Registrasi: form daftar dengan validasi +
password_hash, kirim email verifikasi. - Reset password: token acak kedaluwarsa via email (jangan pernah kirim password lama!).
- OAuth: "Login dengan Google" memakai library
league/oauth2-google. - Framework: pindahkan ke Laravel: semua konsep ini (hash, session, guard, CSRF) sudah built-in dan lebih rapi.
Setiap langkah memakai ulang pola keamanan dari proyek ini. Kuasai fondasinya, dan framework hanya menjadi "cara yang lebih cepat menulis hal yang sama".
Catatan teknis: Template ini adalah fondasi; langkah berikutnya adalah mengganti
$usersarray dengan database (prepared statement) dan menambah fitur "ingat saya" dengan token. Kerangka keamanannya (hash, regenerate, guard, logout total) tetap sama persis.
Tantangan
Ingat saya
Tambahkan checkbox "Ingat saya" di login: jika dicentang, set cookie ingat_user berisi username selama 7 hari. Saat buka login.php dan cookie ada, isi otomatis field username.
Tugas
Tugas: Sistem Login Aman
Buat 4 file sesuai spesifikasi modul ini (login, dashboard, logout, users dengan password ter-hash). Kirim kode keempat file (pisahkan dengan komentar // ===== login.php =====) untuk dinilai AI.
Kriteria penilaian:
- Password disimpan sebagai hash, verifikasi dengan password_verify()
- session_regenerate_id(true) setelah login
- dashboard.php menolak akses tanpa login (redirect)
- logout menghancurkan session sepenuhnya
- htmlspecialchars untuk nama user di dashboard
AI tutor akan memeriksa bug, kesalahan syntax, dan memberi saran perbaikan.
Kuis Bab
Uji pemahamanmu: Bab 10: Composer, Error & Proyek
Jawab 5 soal berikut, lalu tekan "Periksa Jawaban".
1.File apa yang TIDAK boleh di-commit ke git dalam project Composer?
2.Apa aturan penamaan PSR-4?
3.Apa yang harus dilakukan dengan error di production?
4.Urutan blok catch yang benar adalah...
5.Apa tujuan pola POST-Redirect-GET?