Salah satu “misteri” bagi para programmer web pemula adalah satu pertanyaan, “Bagaimana cara membuat suatu situs web yang dilengkapi Login dan Logout?” Bahkan setelah menemukan tutorial di Youtube atau membaca buku komputer pemrograman web sekali pun, bagi sebagian mereka tetap adalah hal paling sulit dimengerti. Ini pula yang saya temui pada murid-murid saya, di mana saya mengajar pemrograman web sejak tahun 2004.

Salah satu alasan suatu buku komputer sulit dipahami adalah pembahasan tidak to the point. Halaman web yang seharusnya mudah dipahami menjadi rumit akibat pengarang buku menambahkan kode-kode CSS agar tampilan makin menarik tapi justru makin sulit dipahami pemula.

Karena itu lah, saya mencoba membuat contoh halaman-halaman web sesederhana mungkin agar mudah dipahami. Keindahan dikesampingkan dulu. Yang tidak penting dihapus. Kode-kode pun dibuat sesingkat mungkin.

Langsung saja.
Silakan copy paste kode-kode di bawah ini lalu amati hasilnya di web browser.

Nama file: koneksi.php

<?php
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "";
$dbname = "latihan";

$dsn = "mysql:host=$dbhost;dbname=$dbname;charset=utf8mb4";
$pdo = new PDO($dsn, $dbuser, $dbpass);

PDO singkatan dari PHP Data Objects. Mulai diperkenalkan pada PHP versi 5.1. Dengan PDO, kita bisa berganti antar sistem database (misalnya dari MySQL ke PosgreSQL) dengan mudah tanpa harus mengubah banyak kode program. Selain itu, juga lebih kebal dari serangan SQL Injection. Sebelumnya, kita menggunakan mysql_connect dan mysqli_connect untuk terhubung ke database.

Nama file: setupdb.php

<?php
// Jalankan file ini hanya sekali saja.
// Setelah selesai, sebaiknya diamankan, misalnya
// dipindah ke flashdrive.

include_once("koneksi.php");

// Membuat tabel.
$query = "
create table users (
  username varchar(15),
  realname varchar(30),
  password varchar(60),
  primary key (username)
)";
$pdo->query($query);

// Mengisikan user pertama.
$username = "alda";
$realname = "Alda Alda Saja";
$password = password_hash("rahasia", PASSWORD_DEFAULT);

$query = "
insert into users (username, realname, password)
values (:username, :realname, :password)";
$stmt = $pdo->prepare($query);
$stmt->bindValue(':username', $username, PDO::PARAM_STR);
$stmt->bindValue(':realname', $realname, PDO::PARAM_STR);
$stmt->bindValue(':password', $password, PDO::PARAM_STR);
$stmt->execute();

echo "Setup selesai. File ini boleh dihapus atau diamankan.";

Banyak programmer yang sadar bahwa tidak boleh menyimpan password dalam bentuk plain text, sehingga yang disimpan di database hanyalah hash-nya. Cuma sayangnya, algoritma yang dipakai adalah SHA*. Padahal, bila server berhasil dibobol dan peretas berhasil membobol database, maka dengan bantuan komputer yang cepat, peretas bisa melakukan coba-coba untuk menemukan password akun yang diincar.

Disarankan agar kita menggunakan teknik hashing lambat, misalnya BCrypt. Algoritma BCrypt digunakan oleh beberapa distro Linux dan beberapa perusahaan besar.

Contoh:

Password asli: rahasia
md5(“rahasia”) = ac43724f16e9241d990427ab7c8f4228
sha1(“rahasia”) = 829b36babd21be519fa5f9353daf5dbdb796993e
Bcrypt(“rahasia”) = $2y$12$goTzsElMHZ/if3Um1jBtkeGb5Im8OBsKg3j0epRvo4Rw0j8X2IRCe

Yang disimpan ke database bukan string “rahasia” tapi huruf dan angka panjang yang sulit dikembalikan ke bentuk aslinya. Ada yang unik dengan BCrypt. Bila md5 dan sha1 selalu menghasilkan string yang sama untuk “rahasia”, maka Bcrypt hasilnya selalu berbeda.

Untuk menyiapkan tabel, anda tidak perlu membuat secara manual dari PhpMyAdmin. Cukup jalankan script PHP di atas.

Nama file: menu.php

<?php
echo '<a href="index.php">Beranda</a> | ';

if (isset($_SESSION['username'])) echo '<a href="rahasia.php">Rahasia</a> | ';

if (!isset($_SESSION['username'])) echo '<a href="login.php">Login</a> ';
else echo '<a href="logout.php">Logout</a> ';
echo "<hr>";

Tanda seru (!) pada PHP berarti “not”. if (siswa()) berarti “jika siswa”. if (!siswa()) berarti “jika bukan siswa”.

Nama file: index.php

<?php session_start(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Beranda</title>
</head>

<body>
<?php include_once("menu.php"); 

if (!isset($_SESSION['username'])) {
  echo "Anda adalah Guest. Silakan login terlebih dulu.";
}
else {
  echo "Selamat datang {$_SESSION['realname']}";
};

?>  
</body>
</html>

Sekedar mengingatkan bahwa bila akan menggunakan session, maka harus diawali dengan fungsi session_start().

Nama file: login.php

<?php session_start(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Login</title>
</head>

<body>
<?php include_once("menu.php"); ?>

<form method="post" action="logincek.php">
Username: <input type="text" name="username"><br>
Password: <input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>

Untuk mengirim data rahasia atau data yang jumlahnya besar (banyak), disarankan jangan memakai method=”get” tapi memakai method=”post”.

Nama file: logincek.php

<?php session_start(); 

if (!isset($_POST['username']) || !isset($_POST['password'])) {
  die();
};

include_once("koneksi.php");

$query = "select * from users where username = :username";
$stmt = $pdo->prepare($query);
$stmt->bindValue(':username', $_POST['username'], PDO::PARAM_STR);
$stmt->execute();
$baris = $stmt->fetch();
if ($baris === FALSE) {
  $error = "Username tidak ditemukan.";
}
else {
  if (password_verify($_POST['password'], $baris['password'])) {
    $username = $baris['username'];
    $realname = $baris['realname'];

    $_SESSION['username'] = $username;
    $_SESSION['realname'] = $realname;
  }
  else {
    $error = "Password salah.";
  };
};
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Login</title>
</head>

<body>
<?php include_once("menu.php");

if (isset($error)) {
  echo $error;
}
else {
  echo "Selamat datang $realname.";
};
?>
</body>
</html>

Nama file: rahasia.php

<?php session_start();

if (!isset($_SESSION['username'])) die();
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Halaman Rahasia</title>
</head>

<body>
<?php include_once("menu.php"); ?> 

Ini adalah halaman rahasia yang bisa dilihat bila sudah login.
</body>
</html>

Nama file: logout.php

<?php session_start();

unset($_SESSION['username']);
unset($_SESSION['realname']);
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Logout</title>
</head>

<body>
<?php include_once("menu.php"); ?>

Oke. Anda sudah logout.
</body>
</html>

Sekian.
Semoga mudah dipahami.

Selanjutnya, silakan halaman-halaman web di atas dihias dengan CSS dan ditambah fitur-fitur lainnya agar semakin indah.

Perhatikan:
Anda boleh menggunakan kode-kode di atas untuk dipelajari atau dipakai di proyek pribadi, tapi dilarang menyalin kode-kode di atas, sebagian maupun keseluruhan, untuk dipublikasikan ulang ke media umum, misalnya dalam bentuk blog, video tutorial, maupun buku. Pelanggaran terhadap peringatan ini akan dituntut ke pengadilan. Sebaiknya buat tautan yang merujuk ke halaman ini.