Cookies dan Sessions adalah dua teknologi fundamental dalam pengembangan web yang memungkinkan aplikasi untuk mengingat informasi tentang user. Dalam tutorial ini, Anda akan mempelajari cara menggunakan cookies dan sessions di PHP untuk membuat sistem login yang aman dan fungsional.
📋 Daftar Isi
Apa itu Cookies?
Cookies adalah file kecil yang disimpan oleh server di komputer user untuk mengidentifikasi dan mengingat informasi tentang user tersebut. Cookies membantu menyimpan data dan informasi untuk mengenali seorang user ketika mereka mengunjungi website kembali.
✅ Kegunaan Cookies
- Menyimpan preferensi user
- Mengingat login status
- Tracking aktivitas user
- Menyimpan items di shopping cart
- Personalisasi konten
⚠️ Karakteristik Cookies
- Disimpan di browser user
- Memiliki waktu expired
- Dapat dihapus oleh user
- Ada batasan ukuran (4KB)
- Bisa diakses oleh JavaScript
Syntax Cookies di PHP
Untuk membuat cookies di PHP, kita menggunakan fungsi setcookie() dengan syntax berikut:
| Parameter | Deskripsi | Contoh |
|---|---|---|
| name | Nama dari cookie (wajib) | "username" |
| value | Nilai yang disimpan dalam cookie | "john123" |
| expire | Waktu kadaluarsa (dalam Unix timestamp) | time() + 86400 |
| path | Path di server dimana cookie tersedia | "/" (seluruh website) |
| domain | Domain dimana cookie tersedia | "example.com" |
| secure | Cookie hanya dikirim melalui HTTPS | true/false |
| httponly | Cookie hanya diakses melalui HTTP (tidak oleh JavaScript) | true/false |
setcookie() harus dipanggil sebelum output HTML apapun. Pastikan tidak ada spasi atau kode sebelum tag <?php.
Membuat dan Mengelola Cookies
Contoh 1: Membuat Cookie Sederhana
Mari kita buat cookie yang akan menyimpan username dan expired setelah 2 hari:
<?php
// Membuat cookie yang expired setelah 2 hari
// 2 hari = 2 * 24 jam * 60 menit * 60 detik
setcookie("username", "john123", time() + 2 * 24 * 60 * 60);
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Contoh Cookie PHP</title>
</head>
<body>
<h1>Demo PHP Cookies</h1>
<?php
// Mengecek apakah cookie sudah di-set
if (isset($_COOKIE["username"])) {
echo "<h2>Username: {$_COOKIE['username']}</h2>";
echo "<p>Cookie berhasil disimpan!</p>";
} else {
echo "<h2>Tidak ada cookie yang di-set</h2>";
echo "<p>Cookie akan muncul setelah page di-reload.</p>";
}
?>
<p><a href="">Reload halaman ini</a> untuk melihat cookie!</p>
</body>
</html>
Cookie baru akan tersedia di
$_COOKIE pada request berikutnya. Saat pertama kali set, cookie sudah dikirim ke browser, tapi variabel $_COOKIE belum ter-update di script yang sama.
Mengakses Cookie
Untuk mengakses cookie yang sudah dibuat, kita menggunakan superglobal $_COOKIE yang bekerja seperti associative array:
<?php
// Membaca cookie
if (isset($_COOKIE["username"])) {
$username = $_COOKIE["username"];
echo "Selamat datang kembali, " . htmlspecialchars($username);
} else {
echo "Cookie tidak ditemukan. Silakan login.";
}
// Menampilkan semua cookies yang ada
echo "<h3>Semua Cookies:</h3>";
echo "<pre>";
print_r($_COOKIE);
echo "</pre>";
?>
Menghapus Cookie
Untuk menghapus cookie, kita menggunakan fungsi setcookie() yang sama tetapi dengan nilai kosong dan waktu expired yang sudah lewat:
<?php
// Cara 1: Set expired time ke masa lalu (60 detik yang lalu)
setcookie("username", "", time() - 60);
// Cara 2: Set expired time ke 0
setcookie("username", "", 0);
// Cara 3: Lebih eksplisit
setcookie("username", "", time() - 3600, "/");
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Hapus Cookie</title>
</head>
<body>
<h1>Cookie Dihapus</h1>
<?php
if (isset($_COOKIE["username"])) {
echo "<p>Cookie masih ada: {$_COOKIE['username']}</p>";
echo "<p>Reload halaman untuk melihat cookie terhapus.</p>";
} else {
echo "<p>Cookie sudah dihapus!</p>";
}
?>
<p><a href="">Reload halaman</a></p>
</body>
</html>
- Browser perlu di-refresh untuk melihat perubahan
- Parameter path dan domain harus sama dengan saat membuat cookie
- Beberapa browser mungkin cache cookie, coba clear browser cache jika tidak terhapus
Contoh Praktis: Cookie untuk "Remember Me"
<?php
// Memproses login dengan opsi "Remember Me"
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST["username"];
$password = $_POST["password"];
$remember = isset($_POST["remember"]);
// Validasi login (contoh sederhana)
if ($username == "admin" && $password == "123") {
if ($remember) {
// Set cookie untuk 30 hari jika Remember Me di-check
setcookie("remember_user", $username, time() + (30 * 24 * 60 * 60), "/");
echo "Cookie 'Remember Me' telah di-set untuk 30 hari.";
} else {
// Hapus cookie jika ada
setcookie("remember_user", "", time() - 3600, "/");
}
header("Location: dashboard.php");
exit();
} else {
$error = "Username atau password salah!";
}
}
// Cek apakah ada cookie remember_user
$saved_username = isset($_COOKIE["remember_user"]) ? $_COOKIE["remember_user"] : "";
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Login dengan Remember Me</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 400px;
margin: 50px auto;
padding: 20px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
button {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
width: 100%;
}
button:hover {
background-color: #45a049;
}
.error {
color: red;
margin-bottom: 10px;
}
</style>
</head>
<body>
<h2>Login</h2>
<?php if (isset($error)): ?>
<p class="error"><?php echo $error; ?></p>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label>Username:</label>
<input type="text" name="username"
value="<?php echo htmlspecialchars($saved_username); ?>"
required>
</div>
<div class="form-group">
<label>Password:</label>
<input type="password" name="password" required>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="remember"
<?php echo $saved_username ? 'checked' : ''; ?>>
Remember Me (30 hari)
</label>
</div>
<button type="submit">Login</button>
</form>
</body>
</html>
Apa itu Session?
Session adalah mekanisme untuk menyimpan informasi yang dapat diakses di berbagai halaman dalam satu website. Berbeda dengan cookies yang disimpan di browser client, session menyimpan data di server.
🍪 Cookies
- Penyimpanan: Di browser client
- Ukuran: Maksimal 4KB
- Keamanan: Kurang aman (bisa dimodifikasi)
- Expired: Bisa diatur
- Akses: Client & Server
🔐 Sessions
- Penyimpanan: Di server
- Ukuran: Tergantung server
- Keamanan: Lebih aman
- Expired: Otomatis saat browser ditutup
- Akses: Hanya server
Cara Kerja Session
Proses Session di PHP:
- Server membuat Session ID unik untuk setiap user
- Session ID disimpan di cookie browser user (bernama PHPSESSID)
- Data session sebenarnya disimpan di server
- Setiap request, browser mengirim Session ID
- Server menggunakan Session ID untuk mengambil data session yang sesuai
Fungsi-Fungsi Session di PHP
PHP menyediakan beberapa fungsi built-in untuk mengelola session:
| Fungsi | Deskripsi | Contoh Penggunaan |
|---|---|---|
| session_start() | Memulai session atau melanjutkan session yang ada. HARUS dipanggil di awal script sebelum HTML. | session_start(); |
| session_unset() | Menghapus semua variabel session, tapi session tetap aktif | session_unset(); |
| session_destroy() | Menghancurkan semua data session dan mengakhiri session | session_destroy(); |
| session_id() | Mendapatkan atau mengatur session ID | echo session_id(); |
| session_regenerate_id() | Membuat session ID baru (untuk keamanan) | session_regenerate_id(true); |
Menggunakan Session - Contoh Dasar
<?php
// WAJIB: Mulai session di awal script
session_start();
// Menyimpan data ke session (seperti associative array)
$_SESSION["username"] = "admin";
$_SESSION["email"] = "admin@example.com";
$_SESSION["login_time"] = date("Y-m-d H:i:s");
$_SESSION["itemCount"] = 3;
// Membaca data dari session
echo "<h2>Data Session:</h2>";
echo "Username: " . $_SESSION["username"] . "<br>";
echo "Email: " . $_SESSION["email"] . "<br>";
echo "Login Time: " . $_SESSION["login_time"] . "<br>";
echo "Items in Cart: " . $_SESSION["itemCount"] . "<br>";
// Mengecek apakah variabel session ada
if (isset($_SESSION["username"])) {
echo "<p>User sudah login!</p>";
}
// Menampilkan semua session
echo "<h3>Semua Session Data:</h3>";
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
// Menghapus satu variabel session
unset($_SESSION["itemCount"]);
// Session ID
echo "<p>Session ID: " . session_id() . "</p>";
?>
Membuat Sistem Login dengan Session
Sekarang kita akan membuat sistem login lengkap yang menggunakan session. Sistem ini akan memiliki beberapa halaman:
- login.php - Halaman login
- home.php - Halaman utama (protected)
- contact.php - Halaman kontak (protected)
- nav.php - Navigation dan validasi session
- logout.php - Proses logout
- function.php - Helper functions
📋 Langkah-Langkah Sistem Login
File 1: login.php - Halaman Login
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - Sistem Manajemen</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.login-container {
background: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
width: 100%;
max-width: 400px;
}
h1 {
text-align: center;
color: #333;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: bold;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 16px;
transition: border-color 0.3s;
}
input[type="text"]:focus,
input[type="password"]:focus {
outline: none;
border-color: #667eea;
}
input[type="submit"] {
width: 100%;
padding: 12px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: transform 0.2s;
}
input[type="submit"]:hover {
transform: translateY(-2px);
}
.info {
text-align: center;
margin-top: 20px;
padding: 10px;
background-color: #e7f3ff;
border-radius: 5px;
font-size: 14px;
}
</style>
</head>
<body>
<div class="login-container">
<h1>🔐 Login</h1>
<form action="home.php" method="post">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username"
placeholder="Masukkan username" required>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password"
placeholder="Masukkan password" required>
</div>
<input type="submit" name="submit" value="Log In">
</form>
<div class="info">
<strong>Demo Credentials:</strong><br>
Username: admin<br>
Password: 123
</div>
</div>
</body>
</html>
File 2: function.php - Helper Functions
<?php
/**
* Fungsi untuk redirect ke halaman login
* dan menghentikan eksekusi script
*/
function quit() {
// Header 303 untuk redirect HTTP POST request
header("Location: login.php", true, 303);
die(); // Menghentikan eksekusi script
}
/**
* Fungsi untuk validasi apakah user sudah login
*/
function checkLogin() {
if (!isset($_SESSION["username"])) {
quit();
}
}
/**
* Fungsi untuk sanitize input
*/
function sanitize($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
Status code 303 (See Other) digunakan untuk redirect setelah POST request. Ini memberitahu browser untuk melakukan GET request ke URL tujuan, mencegah re-submission form saat user refresh halaman.
File 3: nav.php - Navigation dan Session Validation
<?php
// Mulai session (jika belum dimulai)
session_start();
// Include helper functions
require_once("function.php");
// Cek apakah request dari form submit atau sudah ada session
if (!isset($_POST["submit"]) && !isset($_SESSION["username"])) {
// Tidak ada POST data dan tidak ada session → redirect ke login
quit();
}
// Jika request dari form submit
if (isset($_POST["submit"])) {
// Ambil data dari form
$username = sanitize($_POST["username"]);
$password = sanitize($_POST["password"]);
// Validasi username dan password
// (dalam aplikasi real, gunakan database dan password hashing)
if (!isset($_SESSION["username"]) &&
$username == "admin" &&
$password == "123") {
// Login berhasil - buat session
$_SESSION["username"] = $username;
$_SESSION["login_time"] = date("Y-m-d H:i:s");
// Regenerate session ID untuk keamanan
session_regenerate_id(true);
} else {
// Login gagal - redirect ke login
quit();
}
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
nav {
background-color: #333;
padding: 15px 0;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
nav a {
color: white;
text-decoration: none;
padding: 10px 20px;
margin: 0 5px;
border-radius: 5px;
transition: background-color 0.3s;
}
nav a:hover {
background-color: #555;
}
nav span {
color: #4CAF50;
padding: 10px 20px;
font-weight: bold;
}
.logout-btn {
background-color: #f44336;
float: right;
}
.logout-btn:hover {
background-color: #da190b;
}
</style>
</head>
<body>
<nav>
<a href="home.php">🏠 Home</a>
<a href="contact.php">📧 Contact</a>
<?php if (isset($_SESSION["username"])): ?>
<span>
👤 Halo, <?php echo htmlspecialchars($_SESSION["username"]); ?>!
</span>
<a href="logout.php" class="logout-btn">🚪 Log Out</a>
<?php endif; ?>
</nav>
File 4: home.php - Halaman Utama
<?php
// Include navigation (sudah ada session_start di dalamnya)
require("nav.php");
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Home - Dashboard</title>
<style>
.container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
.welcome-box {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px;
border-radius: 10px;
margin-bottom: 30px;
text-align: center;
}
.info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-top: 30px;
}
.info-card {
background: white;
padding: 25px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.info-card h3 {
color: #667eea;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container">
<div class="welcome-box">
<h1>🎉 Selamat Datang di Dashboard!</h1>
<p>Anda berhasil login sebagai
<strong><?php echo htmlspecialchars($_SESSION["username"]); ?></strong>
</p>
</div>
<div class="info-grid">
<div class="info-card">
<h3>📊 Statistik</h3>
<p>Total Pengunjung: 1,234</p>
<p>Produk Terjual: 567</p>
</div>
<div class="info-card">
<h3>🕐 Info Login</h3>
<p>Username: <?php echo htmlspecialchars($_SESSION["username"]); ?></p>
<p>Login Time: <?php echo $_SESSION["login_time"]; ?></p>
<p>Session ID: <?php echo substr(session_id(), 0, 10) . "..."; ?></p>
</div>
<div class="info-card">
<h3>🔔 Notifikasi</h3>
<p>✅ Anda memiliki 3 pesan baru</p>
<p>✅ 2 tugas menunggu approval</p>
</div>
</div>
<div style="margin-top: 30px; padding: 20px; background-color: #f0f4ff; border-radius: 8px;">
<h3>🔐 Session Data (Debug Info):</h3>
<pre><?php print_r($_SESSION); ?></pre>
</div>
</div>
</body>
</html>
File 5: contact.php - Halaman Kontak
<?php
// Include navigation
require("nav.php");
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Contact - Hubungi Kami</title>
<style>
.container {
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
}
.contact-box {
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
.contact-info {
line-height: 2;
}
.contact-info p {
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<div class="contact-box">
<h1>📧 Hubungi Kami</h1>
<div class="contact-info">
<p><strong>📍 Alamat:</strong></p>
<p>Jl. Contoh No. 123, Jakarta 12345</p>
<p><strong>📞 Telepon:</strong></p>
<p>+62 21 1234 5678</p>
<p><strong>✉️ Email:</strong></p>
<p>info@example.com</p>
<p><strong>🕐 Jam Operasional:</strong></p>
<p>Senin - Jumat: 09:00 - 17:00 WIB</p>
<p>Sabtu: 09:00 - 13:00 WIB</p>
</div>
<div style="margin-top: 30px; padding: 15px; background-color: #f0f4ff; border-radius: 5px;">
<p>👤 Logged in as: <strong><?php echo htmlspecialchars($_SESSION["username"]); ?></strong></p>
</div>
</div>
</div>
</body>
</html>
File 6: logout.php - Proses Logout
<?php
// Mulai session
session_start();
// Hapus semua variabel session
session_unset();
// Hancurkan session
session_destroy();
// Redirect ke halaman login
header("Location: login.php");
exit();
?>
✅ Cara Kerja Logout:
session_start()- Memulai/melanjutkan sessionsession_unset()- Menghapus semua variabel di$_SESSIONsession_destroy()- Menghancurkan data session di serverheader("Location: login.php")- Redirect ke halaman login
Validasi User dari File
Dalam praktik yang lebih baik, data user sebaiknya tidak di-hardcode di dalam script. Mari kita buat sistem yang membaca credentials dari file eksternal menggunakan pendekatan Object-Oriented Programming (OOP).
Step 1: Membuat File Credentials
admin;123
password_hash().
Step 2: Membuat Class Credential
<?php
/**
* Class untuk mengelola credentials user dari file
*/
class Credential {
private $file;
public $username;
public $password;
/**
* Constructor - membuka file saat object dibuat
*/
function __construct() {
$this->file = fopen("user.txt", "r") or die("Unable to open file");
}
/**
* Destructor - menutup file saat object dihapus
*/
function __destruct() {
if ($this->file) {
fclose($this->file);
}
}
/**
* Membaca file dan memproses username & password
*/
function readFile() {
// Membaca satu baris dari file
$info = fgets($this->file);
// Memisahkan berdasarkan semicolon
$infoArray = explode(";", $info);
// Set username dan password
$this->username = trim($infoArray[0]);
$this->password = trim($infoArray[1]);
}
/**
* Getter untuk username
*/
function getUsername() {
return $this->username;
}
/**
* Getter untuk password
*/
function getPassword() {
return $this->password;
}
/**
* Validasi login
*/
function validateLogin($inputUsername, $inputPassword) {
$this->readFile();
return ($inputUsername === $this->username &&
$inputPassword === $this->password);
}
}
?>
- Constructor: Membuka file otomatis saat object dibuat
- Destructor: Menutup file otomatis saat object dihapus
- Encapsulation: Atribut private dengan getter methods
- Method: Fungsi untuk memproses dan validasi data
Step 3: Update nav.php untuk Menggunakan Class Credential
<?php
session_start();
require_once("function.php");
require_once("Credential.php");
// Cek apakah request dari form submit atau sudah ada session
if (!isset($_POST["submit"]) && !isset($_SESSION["username"])) {
quit();
}
// Jika request dari form submit
if (isset($_POST["submit"])) {
$username = sanitize($_POST["username"]);
$password = sanitize($_POST["password"]);
// Buat object Credential
$user = new Credential();
$user->readFile();
// Validasi menggunakan data dari file
if (!isset($_SESSION["username"]) &&
$username == $user->getUsername() &&
$password == $user->getPassword()) {
// Login berhasil
$_SESSION["username"] = $username;
$_SESSION["login_time"] = date("Y-m-d H:i:s");
session_regenerate_id(true);
} else {
// Login gagal
quit();
}
}
?>
<nav>
<a href="home.php">🏠 Home</a>
<a href="contact.php">📧 Contact</a>
<?php if (isset($_SESSION["username"])): ?>
<span>
👤 Halo, <?php echo htmlspecialchars($_SESSION["username"]); ?>!
</span>
<a href="logout.php" class="logout-btn">🚪 Log Out</a>
<?php endif; ?>
</nav>
Penjelasan Detail: Constructor dan Destructor
// Constructor - dipanggil otomatis saat: $user = new Credential();
function __construct() {
// Membuka file untuk dibaca
$this->file = fopen("user.txt", "r") or die("Unable to open file");
}
// Destructor - dipanggil otomatis saat:
// 1. Script selesai dijalankan
// 2. Object di-unset: unset($user)
// 3. Tidak ada lagi reference ke object
function __destruct() {
// Menutup file yang sudah dibuka
if ($this->file) {
fclose($this->file);
}
}
- Otomatis membuka file saat object dibuat
- Otomatis menutup file saat object tidak digunakan lagi
- Mencegah memory leak dan file handle yang tidak tertutup
- Kode lebih bersih dan mudah di-maintain
Penjelasan: Membaca dan Memproses File
function readFile() {
// 1. Membaca satu baris dari file
$info = fgets($this->file);
// Hasil: "admin;123\n"
// 2. Memecah string berdasarkan delimiter ";"
$infoArray = explode(";", $info);
// Hasil: Array ( [0] => "admin", [1] => "123\n" )
// 3. Mengambil username dari array index 0
$this->username = trim($infoArray[0]);
// Hasil: "admin" (tanpa whitespace)
// 4. Mengambil password dari array index 1
$this->password = trim($infoArray[1]);
// Hasil: "123" (tanpa whitespace dan newline)
}
Best Practices untuk Cookies dan Sessions
1. Keamanan Session
<?php
// 1. Set session configuration SEBELUM session_start()
ini_set('session.cookie_httponly', 1); // Tidak bisa diakses JavaScript
ini_set('session.cookie_secure', 1); // Hanya dikirim via HTTPS
ini_set('session.use_only_cookies', 1); // Hanya gunakan cookies
ini_set('session.cookie_samesite', 'Strict'); // Proteksi CSRF
// 2. Set session timeout (30 menit)
ini_set('session.gc_maxlifetime', 1800);
ini_set('session.cookie_lifetime', 1800);
// 3. Mulai session
session_start();
// 4. Regenerate session ID secara berkala untuk mencegah session fixation
if (!isset($_SESSION['created'])) {
$_SESSION['created'] = time();
} else if (time() - $_SESSION['created'] > 1800) {
// Session lebih dari 30 menit, regenerate ID
session_regenerate_id(true);
$_SESSION['created'] = time();
}
// 5. Validasi IP address dan User Agent
if (!isset($_SESSION['user_ip'])) {
$_SESSION['user_ip'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
} else {
if ($_SESSION['user_ip'] !== $_SERVER['REMOTE_ADDR'] ||
$_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT']) {
// Possible session hijacking - destroy session
session_unset();
session_destroy();
header("Location: login.php");
exit();
}
}
?>
2. Password Hashing
<?php
// ❌ JANGAN LAKUKAN INI (password dalam plain text)
$password = "123";
// ✅ LAKUKAN INI (password hashing)
// Saat registrasi user baru
$plainPassword = "123";
$hashedPassword = password_hash($plainPassword, PASSWORD_DEFAULT);
// Simpan $hashedPassword ke database/file
// Saat login - verifikasi password
$inputPassword = $_POST["password"];
$storedHash = "hash_dari_database"; // Ambil dari database
if (password_verify($inputPassword, $storedHash)) {
echo "Login berhasil!";
} else {
echo "Password salah!";
}
// Contoh hash yang dihasilkan:
// $2y$10$YourRandomHashedPasswordHere...
?>
3. Mencegah Session Fixation
<?php
session_start();
// Setelah login berhasil, SELALU regenerate session ID
if ($loginSuccessful) {
// Parameter true menghapus session file lama
session_regenerate_id(true);
$_SESSION["username"] = $username;
$_SESSION["logged_in"] = true;
}
?>
4. CSRF Protection
<?php
session_start();
// Generate CSRF token
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// Di form, tambahkan hidden input
?>
<form method="POST">
<input type="hidden" name="csrf_token"
value="<?php echo $_SESSION['csrf_token']; ?>">
<!-- Form fields lainnya -->
</form>
<?php
// Saat memproses form, validasi token
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) ||
$_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("Invalid CSRF token");
}
// Proses form...
}
?>
5. Session Timeout
<?php
session_start();
// Set timeout duration (30 menit = 1800 detik)
$timeout_duration = 1800;
// Cek apakah ada last activity time
if (isset($_SESSION['LAST_ACTIVITY'])) {
// Hitung waktu idle
$elapsed_time = time() - $_SESSION['LAST_ACTIVITY'];
if ($elapsed_time > $timeout_duration) {
// Session timeout - destroy dan redirect
session_unset();
session_destroy();
header("Location: login.php?timeout=1");
exit();
}
}
// Update last activity time
$_SESSION['LAST_ACTIVITY'] = time();
// Optional: Tampilkan waktu sisa session
$remaining_time = $timeout_duration - (time() - $_SESSION['LAST_ACTIVITY']);
$minutes = floor($remaining_time / 60);
echo "Session akan expired dalam $minutes menit";
?>
6. Proper Cookie Settings
<?php
// Setting cookie dengan keamanan maksimal
setcookie(
"user_token", // name
"token_value", // value
[
'expires' => time() + 86400, // 1 day
'path' => '/', // Available in entire domain
'domain' => 'example.com', // Your domain
'secure' => true, // Only HTTPS
'httponly' => true, // Not accessible via JavaScript
'samesite' => 'Strict' // CSRF protection
]
);
?>
Checklist Keamanan
✅ Checklist untuk Session yang Aman:
- ☑️ Selalu gunakan HTTPS di production
- ☑️ Set
session.cookie_httponly = 1 - ☑️ Set
session.cookie_secure = 1untuk HTTPS - ☑️ Regenerate session ID setelah login
- ☑️ Implementasi session timeout
- ☑️ Validasi IP address dan User Agent
- ☑️ Gunakan password hashing (password_hash/password_verify)
- ☑️ Implementasi CSRF protection
- ☑️ Sanitize semua input user
- ☑️ Gunakan prepared statements untuk database
💡 Latihan: Membuat E-Commerce Sederhana
Buatlah aplikasi e-commerce sederhana menggunakan session dengan fitur berikut:
Fitur yang Harus Ada:
- Login System:
- User dapat login dengan username dan password
- Validasi credentials dari file atau database
- Session untuk menyimpan status login
- Shopping Cart:
- User dapat melihat daftar produk
- User dapat menambah produk ke cart
- Cart disimpan dalam session
- Tampilkan total items dan harga di cart
- Checkout:
- Review items di cart
- Hitung total harga
- Clear cart setelah checkout
- Logout:
- Hapus semua session data
- Redirect ke halaman login
Struktur Session yang Disarankan:
$_SESSION = [
"username" => "john",
"logged_in" => true,
"login_time" => "2024-01-01 10:00:00",
"cart" => [
[
"id" => 1,
"name" => "Laptop",
"price" => 15000000,
"quantity" => 1
],
[
"id" => 2,
"name" => "Mouse",
"price" => 150000,
"quantity" => 2
]
],
"cart_total" => 15300000
];
Bonus Challenge:
- Implementasi "Remember Me" menggunakan cookies
- Tambahkan fitur update quantity di cart
- Tambahkan fitur remove item dari cart
- Simpan history pembelian di session
- Implementasi CSRF protection
Troubleshooting Common Issues
Problem 1: "Headers already sent" Error
Penyebab:
- Ada output (HTML, echo, space) sebelum
header()atausetcookie() - Ada BOM (Byte Order Mark) di awal file
- Ada whitespace sebelum
<?php
Solusi:
- Pastikan tidak ada output sebelum
header() - Gunakan
ob_start()di awal file - Save file dengan encoding UTF-8 without BOM
- Hapus semua whitespace sebelum
<?php
Problem 2: Session Data Hilang
Penyebab:
- Lupa memanggil
session_start() - Session timeout
- Browser cookies disabled
- Session ID berubah tanpa data transfer
Solusi:
- Selalu panggil
session_start()di setiap halaman - Set session timeout yang lebih panjang
- Cek apakah cookies enabled di browser
- Gunakan
session_regenerate_id(true)dengan parameter true
Problem 3: Cookie Tidak Tersimpan
Penyebab:
- Cookie di-set setelah output HTML
- Path atau domain salah
- Browser block third-party cookies
- Expired time sudah lewat
Solusi:
- Set cookie sebelum HTML output
- Periksa path dan domain settings
- Test dengan browser yang berbeda
- Gunakan time() + durasi untuk expired
Perbandingan: Cookies vs Sessions vs Database
| Aspek | Cookies | Sessions | Database |
|---|---|---|---|
| Storage Location | Client (Browser) | Server (File/Memory) | Database Server |
| Capacity | ~4KB per cookie | Tergantung server | Unlimited |
| Security | Low (can be modified) | Medium (server-side) | High (encrypted) |
| Expiration | Set by developer | Browser close/timeout | Manual delete |
| Speed | Fast (local) | Fast (server) | Slower (query) |
| Use Case | Preferences, tracking | Login status, cart | Permanent data |
Kesimpulan
Cookies dan Sessions adalah teknologi fundamental dalam pengembangan web modern yang memungkinkan aplikasi untuk mengingat informasi tentang user. Dengan memahami cara kerja keduanya dan mengimplementasikan best practices keamanan, Anda dapat membuat sistem login dan manajemen user yang aman dan efisien.
- Cookies: Disimpan di client, cocok untuk preferensi dan "remember me"
- Sessions: Disimpan di server, lebih aman untuk data sensitif
- Keamanan: Selalu gunakan HTTPS, password hashing, dan CSRF protection
- Best Practice: Kombinasikan cookies dan sessions sesuai kebutuhan
- Validation: Selalu validasi dan sanitize input user

Komentar
Posting Komentar