java php laravel linux mysql sql bootstrap html css query java php laravel linux mysql sql bootstrap html css query

Tuesday, October 13, 2026

keamanan aplikasi web php

🛡️🔐
Keamanan WebPHP & MySQLHash PasswordSQL InjectionXSSHak Akses

Amankan Data Pasien: Hak Akses Pengguna, Hash Password, Perlindungan SQL Injection dan XSS

Pasang gembok berlapis di aplikasi data pasienmu, langsung praktik di XAMPP.

⏱️
12 menit
Estimasi baca
🎯
Lanjut
Level
📅
2026
Tahun

📚 Artikel 14 dari 16 dalam seri Pemrograman Web D4 MIK · CPMK 4 · Sub-CPMK 9

Bayangkan kamu bekerja di sebuah klinik. Rekam medis pasien ditaruh di lemari tanpa kunci, dan siapa pun yang lewat boleh membuka, membaca, bahkan mencoret isinya. Ngeri, kan? Nah, itulah yang terjadi pada aplikasi web yang tidak aman. Diagnosis, keluhan, sampai alamat pasien bisa bocor hanya karena satu form yang lupa dijaga.

Di artikel ke-14 ini kamu akan belajar keamanan aplikasi web PHP secara praktis: mengacak password dengan hash, membatasi hak akses pengguna, serta menangkal SQL Injection dan XSS. Semua dipraktikkan di XAMPP dengan data pasien fiktif, jadi aman dicoba berkali-kali. Siap memasang gembok di aplikasi pasienmu?

🎓 Capaian Sub-CPMK 9
Kamu mampu menerapkan authentication, validasi, dan perlindungan dasar terhadap aplikasi web pengelolaan data kesehatan.

Mengapa Keamanan Aplikasi Web PHP Wajib untuk Data Pasien?

Data kesehatan termasuk data paling sensitif. UU Pelindungan Data Pribadi (UU No. 27 Tahun 2022) menggolongkannya sebagai data pribadi yang bersifat spesifik. Jadi, sebagai calon profesional MIK, tugasmu bukan cuma membuat aplikasi yang jalan, tetapi aplikasi yang menjaga amanah. Kabar baiknya, ada empat pertahanan dasar yang bisa kamu pasang hari ini. Semuanya terangkum dalam satu rumus:

🔐 RUMUS PENGAMANAN
Keamanan = Authentication + Authorization + Validasi Input + Escape Output
Siapa kamu (login) · Apa yang boleh kamu lakukan (hak akses) · Apakah kiriman kamu aman (prepared statement) · Apakah tampilan kamu aman (htmlspecialchars)

Setiap ancaman punya padanan di dunia klinik. Simak tabel ini sebelum kita praktik:

AncamanAnalogi di klinikDampakPertahanan
Password polosKunci ditempel di pintuAkun dokter bisa dipakai orang lainpassword_hash()
Hak akses longgarSemua staf pegang kunci ruang arsipPetugas pendaftaran bisa menghapus pasienCek role di server
SQL InjectionMenyelipkan perintah palsu ke petugasSeluruh tabel pasien bocorPrepared statement
XSSSelebaran jebakan di papan pengumumanScript jahat jalan di browser stafhtmlspecialchars()
🔥 Fakta Menarik
Di daftar OWASP Top 10 edisi 2021, Broken Access Control berada di peringkat pertama (A01), sedangkan Injection, yang mencakup SQL Injection dan XSS, ada di peringkat ketiga (A03). Tiga dari empat pertahanan di artikel ini langsung menjawab daftar tersebut.

Siapkan Lab Praktik: Database, Folder, dan Koneksi

1
Nyalakan XAMPP
Buka XAMPP Control Panel, lalu klik Start pada Apache dan MySQL sampai keduanya berwarna hijau.
2
Siapkan tabel di phpMyAdmin
Buka http://localhost/phpmyadmin, pilih database db_klinik, masuk tab SQL, lalu jalankan kode berikut. Tabel users berasal dari Artikel 13.
📄 phpMyAdmin → tab SQL
CREATE TABLE IF NOT EXISTS pasien (
  id INT AUTO_INCREMENT PRIMARY KEY,
  no_rm VARCHAR(10) NOT NULL,
  nama VARCHAR(100) NOT NULL,
  keluhan VARCHAR(255)
);
INSERT INTO pasien (no_rm, nama, keluhan) VALUES
('RM-001', 'Budi Santoso (fiktif)', 'Demam 3 hari'),
('RM-002', 'Sari Wulandari (fiktif)', 'Batuk kronis');
ALTER TABLE users MODIFY password VARCHAR(255) NOT NULL;
ALTER TABLE users ADD role ENUM('admin','dokter','petugas') NOT NULL DEFAULT 'petugas';
⚠️ Perhatian
Kalau kolom role sudah ada dari Artikel 13, lewati baris ALTER TABLE ... ADD role agar tidak muncul error Duplicate column name.
3
Buat folder kerja dan file koneksi
Buat folder C:\xampp\htdocs\klinik, buka di Sublime Text, lalu simpan file berikut.
📄 koneksi.php
<?php
$koneksi = mysqli_connect('localhost', 'root', '', 'db_klinik');
if (!$koneksi) {
    die('Koneksi gagal: ' . mysqli_connect_error());
}
mysqli_set_charset($koneksi, 'utf8mb4');

Keamanan Aplikasi Web PHP Dimulai dari Hash Password

Hash itu seperti blender: buah masuk, jadi jus, dan jus tidak bisa dikembalikan jadi buah. Fungsi password_hash() mengubah password jadi deretan karakter acak yang tidak bisa dibalik, lengkap dengan salt otomatis. Untuk mengecek login, PHP memakai password_verify().

1
Lihat hasil hash
Simpan sebagai hash_demo.php, lalu buka http://localhost/klinik/hash_demo.php.
📄 hash_demo.php
<?php
echo password_hash('rahasia123', PASSWORD_DEFAULT);

Hasil yang diharapkan: teks berawalan $2y$10$ sepanjang 60 karakter. Refresh halaman, hasilnya berubah terus. Itu normal karena salt-nya acak.

2
Simpan password dalam bentuk hash
Ubah proses registrasi di register.php. Perhatikan role diisi tetap petugas dan tidak diambil dari form. Kalau tidak, siapa pun bisa mendaftar sebagai admin!
📄 register.php (bagian proses)
<?php
require 'koneksi.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username']);
    $hash     = password_hash($_POST['password'], PASSWORD_DEFAULT);

    $stmt = mysqli_prepare($koneksi,
        "INSERT INTO users (username, password, role) VALUES (?, ?, 'petugas')");
    mysqli_stmt_bind_param($stmt, 'ss', $username, $hash);
    mysqli_stmt_execute($stmt);
    echo 'Registrasi berhasil. Silakan login.';
}
// Form HTML tetap sama seperti Artikel 13
3
Verifikasi saat login
Ubah login.php agar membandingkan password dengan password_verify(), lalu simpan role ke session.
📄 login.php (bagian proses)
<?php
require 'koneksi.php';
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username']);
    $stmt = mysqli_prepare($koneksi,
        "SELECT id, password, role FROM users WHERE username = ?");
    mysqli_stmt_bind_param($stmt, 's', $username);
    mysqli_stmt_execute($stmt);
    $user = mysqli_fetch_assoc(mysqli_stmt_get_result($stmt));

    if ($user && password_verify($_POST['password'], $user['password'])) {
        session_regenerate_id(true);
        $_SESSION['id_user'] = $user['id'];
        $_SESSION['role']    = $user['role'];
        header('Location: cari_pasien.php');
        exit;
    }
    $error = 'Username atau password salah.';
}
4
Cek hasilnya di phpMyAdmin
Daftar user baru, lalu buka tabel users. Kolom password harus berisi teks $2y$10$..., bukan password aslinya. Login pun harus berhasil.
💡 Tips
Jangan pakai md5() atau sha1() untuk password. Keduanya terlalu cepat dihitung sehingga mudah ditebak mesin. Dokumentasi resmi PHP menganjurkan password_hash() untuk menyimpan password.

Keamanan Aplikasi Web PHP: Atur Hak Akses Pengguna Berdasarkan Role

Di rumah sakit, kartu akses petugas farmasi tidak bisa membuka ruang arsip rekam medis. Prinsipnya sama: setelah login, tiap role hanya boleh melakukan hal yang sesuai tugasnya. Kita rancang dulu pembagiannya:

Fituradmindokterpetugas
Lihat data pasien✅✅✅
Tambah pasien✅❌✅
Ubah keluhan✅✅❌
Hapus pasien✅❌❌
1
Buat satpam bernama auth.php
File ini berisi fungsi pengecekan login dan role. Ada juga fungsi e() yang kita pakai di bagian XSS nanti.
📄 auth.php
<?php
session_start();

function e($teks) {
    return htmlspecialchars($teks ?? '', ENT_QUOTES, 'UTF-8');
}
function wajib_login() {
    if (!isset($_SESSION['id_user'])) {
        header('Location: login.php');
        exit;
    }
}
function wajib_role(array $boleh) {
    wajib_login();
    if (!in_array($_SESSION['role'], $boleh, true)) {
        http_response_code(403);
        exit('Akses ditolak: role kamu tidak boleh membuka halaman ini.');
    }
}
2
Pasang satpam di halaman sensitif
Contohnya halaman hapus pasien yang hanya boleh dibuka admin.
📄 hapus_pasien.php
<?php
require 'auth.php';
require 'koneksi.php';
wajib_role(['admin']);   // hanya admin

$id = (int) $_GET['id'];
$stmt = mysqli_prepare($koneksi, "DELETE FROM pasien WHERE id = ?");
mysqli_stmt_bind_param($stmt, 'i', $id);
mysqli_stmt_execute($stmt);
header('Location: cari_pasien.php');
exit;

Hasil yang diharapkan: login sebagai petugas lalu buka hapus_pasien.php?id=1, maka muncul pesan Akses ditolak. Data pasien tetap aman.

⚡ Insight Penting
Cek role selalu di sisi server. Menyembunyikan tombol hapus di HTML hanya kosmetik, karena orang bisa mengetik URL-nya langsung. Catatan: di aplikasi nyata, penghapusan sebaiknya lewat POST plus token CSRF, topik yang bisa kamu dalami sendiri.

Keamanan Aplikasi Web PHP dari SQL Injection: Pakai Prepared Statement

Bayangkan kamu bicara lisan ke petugas: "Cari pasien bernama Budi, atau tampilkan semua pasien." Kalau petugas menurut mentah-mentah, bocorlah semuanya. Prepared statement itu seperti formulir bersekat: isian nama hanya dianggap data, tidak pernah dianggap perintah.

🔬 Analisis: Query Rentan vs Query Aman
❌ Rentan
"... LIKE '%$cari%'"
Input ' OR 1=1 -- mengubah logika query, sehingga semua pasien tampil.
✅ Aman
"... LIKE ?"
Input yang sama hanya dicari sebagai teks nama. Hasilnya: tidak ada pasien ditemukan.
1
Buat halaman pencarian yang aman
Simpan sebagai cari_pasien.php. Perhatikan tanda ? sebagai penampung data dan bind_param yang mengisinya.
📄 cari_pasien.php
<?php
require 'auth.php';
require 'koneksi.php';
wajib_login();

$cari = $_GET['cari'] ?? '';
$like = '%' . $cari . '%';

$stmt = mysqli_prepare($koneksi,
    "SELECT no_rm, nama, keluhan FROM pasien WHERE nama LIKE ?");
mysqli_stmt_bind_param($stmt, 's', $like);
mysqli_stmt_execute($stmt);
$hasil = mysqli_stmt_get_result($stmt);
?>
<form method="get">
    <input type="text" name="cari" value="<?= e($cari) ?>" placeholder="Cari nama pasien">
    <button type="submit">Cari</button>
</form>
<table border="1" cellpadding="6">
    <tr><th>No. RM</th><th>Nama</th><th>Keluhan</th></tr>
    <?php while ($p = mysqli_fetch_assoc($hasil)) { ?>
    <tr>
        <td><?= e($p['no_rm']) ?></td>
        <td><?= e($p['nama']) ?></td>
        <td><?= e($p['keluhan']) ?></td>
    </tr>
    <?php } ?>
</table>
2
Uji dengan dua masukan
Cari Budi: satu baris muncul. Lalu cari ' OR 1=1 -- (ada spasi di akhir): hasilnya kosong, artinya serangan gagal.
⚠️ Perhatian
Uji coba serangan hanya boleh di localhost milikmu sendiri dengan data fiktif. Menguji payload di sistem orang lain tanpa izin adalah pelanggaran hukum.

Tangkal XSS di Aplikasi Web PHP dengan htmlspecialchars

XSS mirip selebaran jebakan di papan pengumuman klinik: siapa pun yang membaca ikut terkena. Penyerang menyimpan kode <script> di kolom keluhan, dan browser petugas yang membukanya akan menjalankan kode itu. Obatnya sederhana: ubah karakter spesial menjadi teks biasa sebelum ditampilkan.

1
Tanam data uji
Di phpMyAdmin tab SQL, jalankan kode berikut.
📄 phpMyAdmin → tab SQL
INSERT INTO pasien (no_rm, nama, keluhan)
VALUES ('RM-003', 'Tes XSS (fiktif)', '<script>alert(''XSS'')</script>');
2
Lihat versi rentan
Di cari_pasien.php, ubah sementara baris keluhan seperti ini, lalu refresh.
📄 cari_pasien.php (bandingkan)
<td><?= $p['keluhan'] ?></td>      <!-- RENTAN: popup muncul -->
<td><?= e($p['keluhan']) ?></td>   <!-- AMAN: tampil sebagai teks -->
3
Kembalikan versi aman
Pakai kembali e(). Hasil yang diharapkan: tidak ada popup, dan kolom keluhan menampilkan tulisan <script>alert('XSS')</script> apa adanya.
💡 Tips
Biasakan dua kebiasaan ini: validasi saat input masuk (misalnya format No. RM dengan preg_match) dan escape saat data keluar (lewat e()). Salah satu saja tidak cukup.

Error yang Sering Muncul & Cara Mengatasinya

GejalaPenyebabSolusi
Login selalu gagal setelah pakai password_verify()Kolom password masih pendek, atau user lama masih berisi password polosJalankan ALTER ... VARCHAR(255), lalu daftar ulang user lama lewat register.php
Cannot modify header information - headers already sentAda spasi atau teks sebelum <?php, atau file tersimpan dengan BOMPastikan <?php di baris pertama. Di Sublime Text: File → Save with Encoding → UTF-8
Number of variables doesn't match number of parametersJumlah tanda ? tidak sama dengan jumlah huruf tipe di bind_paramSamakan jumlahnya, misalnya dua ? berarti 'ss'
Call to undefined function mysqli_stmt_get_result()Driver mysqlnd tidak aktifPakai XAMPP versi terbaru, lalu restart Apache
Admin tetap kena Akses ditolak$_SESSION['role'] kosong karena belum diisi saat loginCek login.php, pastikan role disimpan, lalu logout dan login ulang
✍️ Latihan Mandiri
  1. Role dokter. Buat ubah_keluhan.php yang hanya bisa dibuka admin dan dokter. Buktikan dengan login sebagai petugas sampai muncul pesan 403.
  2. Tambah pasien aman. Buat tambah_pasien.php dengan prepared statement. Tolak nama kosong dan No. RM yang tidak berformat RM- diikuti angka (gunakan preg_match).
  3. Uji XSS. Masukkan dua payload XSS berbeda ke data fiktif, lalu pastikan semua kolom di halaman daftar pasien tampil aman. Tangkap layar sebagai bukti laporan praktikum.
🏁 Kesimpulan

Aplikasi pasienmu kini punya empat lapis pertahanan: password disimpan dengan hash, hak akses dijaga per role di server, SQL Injection ditutup prepared statement, dan XSS dipadamkan htmlspecialchars(). Ingat, keamanan aplikasi web PHP itu kebiasaan, bukan fitur tambahan. Setiap menerima input, tanya: "aman dimasukkan?" Setiap menampilkan data, tanya: "aman ditampilkan?"

Artikel ini bagian dari seri Pemrograman Web D4 MIK. Di Artikel 15, semua fitur ini kita uji dan dirapikan. Bagaimana hasil praktikmu? Ceritakan di kolom komentar, dan bagikan ke temanmu yang sedang belajar PHP!

💬 Tulis Komentar📤 Bagikan Artikel
🏷️ Tag
#PemrogramanWeb#D4MIK#SQLInjection#XSS#HashPassword
📂 Label
Keamanan Aplikasi Web PHPHak Akses PenggunaKeamanan Data PasienPraktikum XAMPP
📚
Pemrograman Web D4 MIK
Lihat seluruh 16 artikel dalam seri ini
Daftar Isi Artikel →

Monday, October 12, 2026

login logout session php

🔐
Siapa yang Boleh Masuk?
Authentication: Registrasi User, Login, Logout, dan Session. Seri Pemrograman Web D4 MIK, Artikel 13 dari 16.
AuthenticationRegistrasi UserLogin PHPSessionLogout
± 12 menit
Estimasi baca
Lanjut
Level
2026
Tahun

Bayangkan kamu masuk ke rumah sakit tanpa ada satu pun petugas yang menanyakan identitasmu. Siapa saja bisa membuka rekam medis, mengubah diagnosis, bahkan menghapus data kunjungan. Ngeri, kan? Itulah yang terjadi pada aplikasi web tanpa sistem masuk. Di artikel ke-13 seri Pemrograman Web D4 MIK ini, kamu akan membangun login PHP session dari nol: registrasi user, login, proteksi halaman, sampai logout. Semuanya kamu praktikkan langsung di XAMPP dengan studi kasus klinik dan data pasien fiktif. Hasil akhirnya: hanya petugas yang punya akun yang bisa membuka halaman data pasien.

Artikel ini mengunci Sub-CPMK 9 (CPMK 4): kamu mampu menerapkan authentication, validasi, dan perlindungan dasar pada aplikasi web pengelolaan data kesehatan.

Login PHP Session: Cara Kerja Authentication di Balik Layar

Protokol HTTP itu pelupa. Setiap kali browser meminta halaman, server menganggapnya pengunjung baru. Jadi setelah kamu berhasil login di login.php, server tidak otomatis ingat kamu waktu kamu pindah ke dashboard.php. Di sinilah session bekerja.

Anggap saja loket pendaftaran rumah sakit. Setelah petugas memeriksa identitasmu, kamu dikasih gelang pasien bernomor unik. Di setiap ruangan, perawat cukup melihat gelang itu tanpa menanyakan KTP lagi. Dalam PHP, gelang itu adalah session ID yang disimpan browser dalam cookie bernama PHPSESSID. Catatan isinya (kamu siapa) disimpan di server, bukan di browser.

📐 Konsep Utama
Authentication = membuktikan siapa kamu (username + password).
Authorization = menentukan boleh apa kamu (dibahas di Artikel 14).

Alur login PHP session: verifikasi password → simpan penanda di $_SESSION → cek penanda itu di setiap halaman terlindungi.
BROWSER                          SERVER (PHP)
  |-- POST login.php ---------->|  cek username, password_verify()
  |<-- Set-Cookie: PHPSESSID ---|  $_SESSION["user_id"] = 5
  |-- GET dashboard.php ------->|  cookie dibawa, session dikenali
  |<-- halaman dashboard -------|
  |-- GET logout.php ---------->|  session_destroy()
  |<-- redirect ke login.php ---|
🔍 Analisis: Cookie vs Session
🍪 Cookie
Disimpan di browser. Pengguna bisa melihat dan mengubahnya. Cocok untuk hal ringan, misalnya preferensi tampilan. Jangan simpan data sensitif di sini.
🗄️ Session
Datanya disimpan di server. Browser hanya memegang ID-nya. Cocok untuk status login, nama petugas, dan penanda hak akses.
⚡ Insight Penting
Isi $_SESSION tidak pernah dikirim ke browser. Yang dikirim hanya session ID. Karena itu pengguna tidak bisa mengubah dirinya sendiri dari “petugas biasa” menjadi “admin” lewat browser. Tapi kalau ID itu dicuri, orang lain bisa menyamar jadi kamu. Makanya nanti kita pakai session_regenerate_id().

Praktik 1: Registrasi User untuk Login PHP Session

Sebelum ada yang bisa login, harus ada akun. Kita buat aplikasi mini “Klinik Sehat Sentosa” (nama fiktif). Ikuti langkahnya berurutan, ya.

1
Siapkan XAMPP dan folder kerja
Buka XAMPP Control Panel, klik Start pada Apache dan MySQL. Lalu buat folder klinik_auth di C:\xampp\htdocs\. Semua file di artikel ini disimpan di folder itu dengan Sublime Text.
2
Buat tabel users di phpMyAdmin
Buka http://localhost/phpmyadmin, pilih tab SQL, tempel kode berikut, lalu klik Kirim.
📄 query.sql
CREATE DATABASE IF NOT EXISTS db_klinik;
USE db_klinik;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nama_lengkap VARCHAR(100) NOT NULL,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
✅ Hasil yang diharapkan: tabel users muncul di database db_klinik dengan 5 kolom.
🔥 Fakta Menarik
Kolom password sengaja dibuat VARCHAR(255). Dokumentasi resmi PHP menyarankan panjang itu untuk hasil password_hash() karena algoritma bawaan bisa berganti seiring versi PHP. Kalau kolommu terlalu pendek, hash terpotong dan login akan selalu gagal.
3
Buat file koneksi.php
File ini dipanggil oleh semua halaman supaya koneksi database cukup ditulis sekali.
📄 koneksi.php
<?php
$koneksi = mysqli_connect("localhost", "root", "", "db_klinik");

if (!$koneksi) {
    die("Koneksi gagal: " . mysqli_connect_error());
}
mysqli_set_charset($koneksi, "utf8mb4");
4
Buat form registrasi (register.php)
Validasi dasar kita lakukan di sini: kolom tidak boleh kosong, password minimal 8 karakter, konfirmasi harus sama, dan username tidak boleh kembar. Password disimpan dalam bentuk hash, bukan teks asli.
📄 register.php
<?php
require "koneksi.php";
$pesan = "";

if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $nama       = trim($_POST["nama_lengkap"]);
    $username   = trim($_POST["username"]);
    $password   = $_POST["password"];
    $konfirmasi = $_POST["konfirmasi"];

    if ($nama === "" || $username === "" || $password === "") {
        $pesan = "Semua kolom wajib diisi.";
    } elseif (strlen($password) < 8) {
        $pesan = "Password minimal 8 karakter.";
    } elseif ($password !== $konfirmasi) {
        $pesan = "Konfirmasi password tidak sama.";
    } else {
        $cek = mysqli_prepare($koneksi, "SELECT id FROM users WHERE username = ?");
        mysqli_stmt_bind_param($cek, "s", $username);
        mysqli_stmt_execute($cek);
        mysqli_stmt_store_result($cek);

        if (mysqli_stmt_num_rows($cek) > 0) {
            $pesan = "Username sudah dipakai.";
        } else {
            $hash   = password_hash($password, PASSWORD_DEFAULT);
            $simpan = mysqli_prepare($koneksi,
                "INSERT INTO users (nama_lengkap, username, password) VALUES (?, ?, ?)");
            mysqli_stmt_bind_param($simpan, "sss", $nama, $username, $hash);
            mysqli_stmt_execute($simpan);
            $pesan = "Registrasi berhasil! Silakan login.";
        }
    }
}
?>
<!DOCTYPE html>
<html lang="id">
<head><meta charset="UTF-8"><title>Registrasi Petugas</title></head>
<body>
    <h2>Registrasi Petugas Klinik</h2>
    <?php if ($pesan !== "") { echo "<p>" . htmlspecialchars($pesan) . "</p>"; } ?>
    <form method="post">
        <p>Nama lengkap<br><input type="text" name="nama_lengkap"></p>
        <p>Username<br><input type="text" name="username"></p>
        <p>Password<br><input type="password" name="password"></p>
        <p>Ulangi password<br><input type="password" name="konfirmasi"></p>
        <button type="submit">Daftar</button>
    </form>
    <p><a href="login.php">Sudah punya akun? Login</a></p>
</body>
</html>
✅ Hasil yang diharapkan: buka http://localhost/klinik_auth/register.php, daftarkan petugas fiktif (misalnya username petugas_ani). Di phpMyAdmin, kolom password berisi teks acak berawalan $2y$, bukan password aslinya.
💡 Tips
Perhatikan tanda ? pada query. Itu prepared statement: data dari form dikirim terpisah dari perintah SQL. Kebiasaan ini akan jadi tameng utama di Artikel 14 saat kita membahas SQL Injection.

Praktik 2: Login PHP Session dengan password_verify

Sekarang bagian serunya. Alurnya: ambil data user berdasarkan username, cocokkan password dengan password_verify(), lalu simpan penanda login di $_SESSION. Perhatikan juga pesan error yang sengaja dibuat sama untuk username salah maupun password salah, supaya penyerang tidak tahu username mana yang terdaftar.

5
Buat file login.php
Baris session_start() wajib berada paling atas, sebelum output apa pun.
📄 login.php
<?php
session_start();
require "koneksi.php";

if (isset($_SESSION["user_id"])) {
    header("Location: dashboard.php");
    exit;
}

$pesan = "";
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $username = trim($_POST["username"]);
    $password = $_POST["password"];

    $stmt = mysqli_prepare($koneksi,
        "SELECT id, nama_lengkap, password FROM users WHERE username = ?");
    mysqli_stmt_bind_param($stmt, "s", $username);
    mysqli_stmt_execute($stmt);
    $user = mysqli_fetch_assoc(mysqli_stmt_get_result($stmt));

    if ($user && password_verify($password, $user["password"])) {
        session_regenerate_id(true);
        $_SESSION["user_id"] = $user["id"];
        $_SESSION["nama"]    = $user["nama_lengkap"];
        header("Location: dashboard.php");
        exit;
    } else {
        $pesan = "Username atau password salah.";
    }
}
?>
<!DOCTYPE html>
<html lang="id">
<head><meta charset="UTF-8"><title>Login Petugas</title></head>
<body>
    <h2>Login Petugas Klinik</h2>
    <?php if ($pesan !== "") { echo "<p>" . htmlspecialchars($pesan) . "</p>"; } ?>
    <form method="post">
        <p>Username<br><input type="text" name="username"></p>
        <p>Password<br><input type="password" name="password"></p>
        <button type="submit">Masuk</button>
    </form>
    <p><a href="register.php">Belum punya akun? Daftar</a></p>
</body>
</html>
⚠️ Perhatian
Error headers already sent hampir selalu karena ada spasi, baris kosong, atau teks sebelum <?php. Fungsi session_start() dan header() hanya bisa jalan sebelum browser menerima output apa pun. Letakkan blok PHP di baris pertama file.
6
Uji coba login
Buka http://localhost/klinik_auth/login.php. Coba dua skenario: (a) password sengaja salah, (b) username dan password benar.
✅ Hasil yang diharapkan: skenario (a) menampilkan pesan “Username atau password salah.” Skenario (b) memindahkanmu ke dashboard.php (halamannya kita buat di langkah berikutnya, jadi sementara akan muncul error file tidak ditemukan; itu normal).

Praktik 3: Proteksi Halaman dan Logout pada Login PHP Session

Login saja belum cukup. Kalau halaman dashboard.php tidak mengecek session, siapa pun yang mengetik alamatnya langsung bisa masuk. Ibarat pintu depan dijaga satpam tapi pintu belakang terbuka lebar. Solusinya: satu file “penjaga” yang dipanggil di setiap halaman terlindungi.

7
Buat file penjaga (auth.php)
Kalau penanda login tidak ada, pengunjung langsung diusir ke halaman login.
📄 auth.php
<?php
session_start();

if (!isset($_SESSION["user_id"])) {
    header("Location: login.php");
    exit;
}

// cegah browser menyimpan halaman terlindungi di cache
header("Cache-Control: no-store, no-cache, must-revalidate");
8
Buat halaman dashboard.php
Cukup satu baris require "auth.php" di paling atas, maka halaman ini terkunci.
📄 dashboard.php
<?php require "auth.php"; ?>
<!DOCTYPE html>
<html lang="id">
<head><meta charset="UTF-8"><title>Dashboard Klinik</title></head>
<body>
    <h1>Dashboard Klinik Sehat Sentosa</h1>
    <p>Selamat datang, <?= htmlspecialchars($_SESSION["nama"]); ?>!</p>
    <p>Halaman ini hanya bisa dibuka petugas yang sudah login.</p>
    <a href="logout.php">Logout</a>
</body>
</html>
9
Buat logout.php
Logout yang benar punya tiga tahap: kosongkan data session, hapus cookie session ID, lalu hancurkan session di server.
📄 logout.php
<?php
session_start();

$_SESSION = [];

if (ini_get("session.use_cookies")) {
    $p = session_get_cookie_params();
    setcookie(session_name(), "", time() - 42000,
        $p["path"], $p["domain"], $p["secure"], $p["httponly"]);
}

session_destroy();
header("Location: login.php");
exit;
10
Uji tiga skenario
(1) Dalam keadaan belum login, ketik langsung http://localhost/klinik_auth/dashboard.php. (2) Login lalu buka dashboard. (3) Klik Logout, lalu tekan tombol Back di browser.
✅ Hasil yang diharapkan: skenario 1 otomatis dialihkan ke login.php; skenario 2 menampilkan “Selamat datang, nama petugas”; skenario 3 tidak lagi menampilkan isi dashboard.
💡 Tips
Mau melihat “gelang pasien”-mu? Tekan F12 di browser, buka tab Application (atau Storage) lalu Cookies. Kamu akan menemukan PHPSESSID. Hapus cookie itu secara manual, lalu refresh dashboard. Kamu langsung ditendang ke halaman login.

Ini rangkuman fungsi penting yang baru saja kamu pakai. Simpan sebagai contekan:

Fungsi / VariabelTugasnyaDipakai di
session_start()Memulai atau melanjutkan sessionlogin, auth, logout
$_SESSION[]Menyimpan data milik satu pengguna di serverlogin, dashboard
password_hash()Mengubah password jadi hash satu arahregister
password_verify()Mencocokkan password input dengan hashlogin
session_regenerate_id(true)Mengganti session ID setelah login berhasillogin
session_destroy()Menghapus data session di serverlogout

Error yang Sering Muncul & Cara Mengatasinya

Tenang, error itu teman belajar. Ini yang paling sering muncul saat mahasiswa praktik login PHP session di laboratorium:

Pesan / GejalaPenyebabSolusi
Cannot modify header information - headers already sentAda output (spasi, HTML, echo) sebelum session_start() atau header()Pindahkan blok PHP ke baris pertama. Di Sublime Text, simpan dengan File → Save with Encoding → UTF-8 (tanpa BOM).
Undefined array key "user_id"Mengakses $_SESSION sebelum session_start() atau sebelum loginPanggil session_start() dulu, dan cek dengan isset().
Login selalu gagal padahal password benarKolom password terlalu pendek, atau password di database diisi manual tanpa hashUbah jadi VARCHAR(255), lalu daftar ulang lewat register.php.
Duplicate entry ... for key 'username'Username sama sudah ada (kolom bersifat UNIQUE)Pakai username lain, atau pastikan pengecekan di register.php berjalan.
Failed opening required 'koneksi.php'Salah folder atau salah nama filePastikan semua file ada di satu folder htdocs\klinik_auth.
Setelah logout, tombol Back masih menampilkan dashboardBrowser menyimpan halaman di cachePastikan baris Cache-Control di auth.php ada, lalu refresh.

Latihan Mandiri: Kuatkan Authentication Klinikmu

Kerjakan di folder yang sama, lalu simpan tangkapan layar hasilnya sebagai bukti praktikum:

1
Catat waktu login terakhir. Tambahkan kolom last_login (DATETIME) di tabel users, isi dengan NOW() setiap login berhasil, dan tampilkan di dashboard.
2
Lindungi halaman data pasien. Buat daftar_pasien.php yang menampilkan 5 data pasien fiktif dari tabel pasien, dan kunci dengan auth.php. Buktikan halaman itu tidak bisa dibuka tanpa login.
3
Session timeout. Simpan waktu aktivitas terakhir di $_SESSION["waktu_terakhir"]. Jika selisihnya lebih dari 15 menit, otomatis logout. Ini praktik lazim untuk komputer bersama di loket pendaftaran.
📚 Referensi
🏁
Kesimpulan: Pintu Sudah Berpenjaga

Kamu sudah membangun siklus lengkap login PHP session: registrasi dengan password_hash(), login dengan password_verify(), penanda di $_SESSION, proteksi halaman lewat auth.php, dan logout yang membersihkan session sampai tuntas. Inti pelajarannya sederhana: browser hanya memegang “gelang”, sedangkan server yang menentukan siapa yang boleh masuk.

Tapi login baru satu lapis. Di Artikel 14, kita tambah lapisan berikutnya: hak akses per peran, hash password yang lebih dalam, serta perlindungan SQL Injection dan XSS. Bagian mana yang paling bikin kamu penasaran atau tersangkut? Ceritakan di kolom komentar, dan bagikan artikel ini ke teman satu kelompok praktikummu.

💬 Tulis Komentar📲 Bagikan via WhatsApp
Tag:
#PemrogramanWeb#D4MIK#LoginPHP#SessionPHP#Authentication
Label:
Login PHP SessionRegistrasi UserLogout PHPAuthenticationManajemen Informasi Kesehatan
📚 Artikel ini adalah bagian dari seri Pemrograman Web D4 MIK
Lihat Daftar Isi Artikel Pemrograman Web D4 MIK
Semua 16 artikel seri ini, dari dasar PHP sampai keamanan aplikasi.

saifiahmada.com adalah blog belajar programming Indonesia, membahas lengkap materi bahasa pemrograman: code HTML, CSS, Bootstrap, Desain, PHP, MySQL, coding Java, Query, SQL, dan dunia linux