Session dan Autentikasi
Di dunia nyata, tidak semua halaman boleh diakses oleh semua orang. Session dan autentikasi (login) digunakan untuk membatasi akses — hanya pengguna yang sudah login yang bisa mengelola data.
Apa itu Session?
HTTP adalah stateless — artinya server tidak mengingat siapa yang membuat request sebelumnya. Session mengatasi masalah ini dengan menyimpan data pengguna di server.
1. User login → Server membuat session → Server kirim session ID ke browser (cookie)
2. User buka halaman lain → Browser kirim session ID → Server kenali user
3. User logout → Session dihapus
Memulai Session
Session harus dimulai di setiap halaman yang membutuhkannya, dan harus dipanggil sebelum output HTML apapun:
<?php
// WAJIB di baris paling atas, sebelum HTML apapun!
session_start();
// Menyimpan data ke session
$_SESSION['nama'] = 'User';
$_SESSION['email'] = 'User@mail.com';
$_SESSION['login'] = true;
// Membaca data dari session
echo $_SESSION['nama']; // 'User'
// Menghapus satu data session
unset($_SESSION['nama']);
// Menghapus semua session (logout)
session_destroy();
Session harus dimulai sebelum output!
// ❌ ERROR — ada output HTML sebelum session_start()
<html>
<?php session_start(); ?>
// ✅ BENAR — session_start() di baris pertama
<?php session_start(); ?>
<html>
Membuat Sistem Login
1. Tabel User
Buat tabel users di MySQL:
USE belajar_web;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
nama_lengkap VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Tambah user admin (password: admin123)
-- Di PHP, password di-hash dengan password_hash()
2. Script Tambah User
Buat file setup-user.php (jalankan sekali saja):
<?php
require 'config/database.php';
// Hash password — JANGAN simpan password sebagai plain text!
$password_hash = password_hash('admin123', PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (username, password, nama_lengkap) VALUES (?, ?, ?)");
$stmt->execute(['admin', $password_hash, 'Administrator']);
echo "User admin berhasil dibuat!";
echo "<br>Password hash: $password_hash";
password_hash() dan password_verify()
JANGAN PERNAH simpan password sebagai plain text di database!
// Saat REGISTRASI — hash password sebelum simpan
$hash = password_hash('admin123', PASSWORD_DEFAULT);
// Hasilnya seperti: $2y$10$abcdef...
// Saat LOGIN — verifikasi password
$cocok = password_verify('admin123', $hash); // true
$cocok = password_verify('salah', $hash); // false
3. Halaman Login: login.php
<?php
session_start();
// Kalau sudah login, redirect ke dashboard
if (isset($_SESSION['user_id'])) {
header("Location: /buku-tamu/");
exit;
}
require 'config/database.php';
$username = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
// Cari user di database
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
// Verifikasi password
if ($user && password_verify($password, $user['password'])) {
// Login berhasil! Simpan data ke session
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['nama_lengkap'] = $user['nama_lengkap'];
header("Location: /buku-tamu/");
exit;
} else {
$error = "Username atau password salah!";
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', sans-serif;
background: linear-gradient(135deg, #667eea, #764ba2);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.login-card {
background: white;
padding: 40px;
border-radius: 16px;
box-shadow: 0 8px 30px rgba(0,0,0,0.2);
width: 100%;
max-width: 380px;
}
h1 {
text-align: center;
color: #667eea;
margin-bottom: 25px;
font-size: 28px;
}
.form-group { margin-bottom: 18px; }
label { display: block; margin-bottom: 5px; font-weight: 600; color: #444; }
input {
width: 100%;
padding: 12px 14px;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 15px;
}
input:focus { outline: none; border-color: #667eea; }
button {
width: 100%;
padding: 14px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
font-weight: 600;
}
button:hover { background: #5a6fd6; }
.error {
background: #fde8e8;
color: #dc3545;
padding: 10px;
border-radius: 8px;
margin-bottom: 15px;
text-align: center;
font-size: 14px;
}
</style>
</head>
<body>
<div class="login-card">
<h1>🔐 Login</h1>
<?php if ($error): ?>
<div class="error">⚠️ <?= $error ?></div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username"
value="<?= htmlspecialchars($username) ?>" required autofocus>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Masuk</button>
</form>
</div>
</body>
</html>
4. Middleware: Cek Login
Buat file config/auth.php:
<?php
// config/auth.php — Cek apakah user sudah login
session_start();
function cekLogin() {
if (!isset($_SESSION['user_id'])) {
header("Location: /login.php");
exit;
}
}
function isLogin() {
return isset($_SESSION['user_id']);
}
function namaUser() {
return $_SESSION['nama_lengkap'] ?? 'Guest';
}
Cara pakai di halaman yang perlu login:
<?php
require __DIR__ . '/../config/database.php';
require __DIR__ . '/../config/auth.php';
cekLogin(); // Redirect ke login kalau belum login
// ... kode halaman yang dilindungi ...
5. Logout: logout.php
<?php
session_start();
// Hapus semua data session
$_SESSION = [];
// Hapus cookie session
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Hancurkan session
session_destroy();
// Redirect ke login
header("Location: /login.php");
exit;
Update templates/header.php:
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= $title ?? 'Buku Tamu' ?></title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<nav>
<div class="logo">📖 Buku Tamu</div>
<ul class="menu">
<li><a href="/buku-tamu/">Daftar Tamu</a></li>
<li><a href="/buku-tamu/tambah.php">Tambah Baru</a></li>
<?php if (isLogin()): ?>
<li style="margin-left: 20px;">
👤 <?= htmlspecialchars(namaUser()) ?>
| <a href="/logout.php">Logout</a>
</li>
<?php endif; ?>
</ul>
</nav>
<div class="container">
Cookie
Selain session, PHP juga bisa menyimpan data di browser menggunakan cookie:
<?php
// Membuat cookie (tersimpan di browser)
setcookie('tema', 'dark', time() + (86400 * 30)); // Berlaku 30 hari
// 86400 = 1 hari dalam detik
// Membaca cookie
$tema = $_COOKIE['tema'] ?? 'light';
echo "Tema saat ini: $tema";
// Menghapus cookie (set expired di masa lalu)
setcookie('tema', '', time() - 3600);
Contoh: Fitur "Ingat Saya"
<?php
// Di login.php — setelah login berhasil
if (isset($_POST['ingat_saya'])) {
// Simpan token di cookie (berlaku 30 hari)
$token = bin2hex(random_bytes(32)); // Token acak yang aman
setcookie('remember_token', $token, time() + (86400 * 30));
// Simpan token di database juga
$stmt = $pdo->prepare("UPDATE users SET remember_token = ? WHERE id = ?");
$stmt->execute([$token, $user['id']]);
}
<!-- Di form login -->
<label>
<input type="checkbox" name="ingat_saya"> Ingat saya
</label>
Rangkuman Keamanan
:::warning Checklist Keamanan
- ✅ password_hash() — Hash password sebelum simpan
- ✅ password_verify() — Verifikasi password saat login
- ✅ Prepared statement — Cegah SQL Injection
- ✅ htmlspecialchars() — Cegah XSS
- ✅ session_start() — Sebelum output apapun
- ✅ Validasi server-side — Jangan percaya data dari browser
- ✅ HTTPS — Enkripsi data yang dikirim (di production)
:::
Selanjutnya
Sekarang kamu sudah punya semua komponen untuk membuat aplikasi web lengkap! Mari gabungkan semuanya di Project Akhir → — Aplikasi Buku Tamu CRUD dengan login.