Membuat Form Login Yang Lebih Aman

Hampir semua website memerlukan login form. System login adalah bagian yang penting bagi sebuah website untuk menjaga keamanan data. Tutorial php membuat form login yang lebih aman ini akan menjelaskan bagaimana cara memdeteksi akses berbeda. Login di php menggunakan session / sesi yang memerlukan ID session yang dikirim ke browser berupa cookie. Jika cookie ini berhasil dicuri maka sesorang akan bisa mengakses halaman admin tanpa perlu login. Tutorial membuat form login ini akan menjelaskan salah satu cara untuk menangkalnya. Tutorial php ini juga dilengkapi video tutorial yang bisa dilihat di channel Youtube MyPHPtutorials.

Video tutorial membuat form login yang lebih aman

Membuat form login yang lebih aman

Berikut langkah langkah untuk membuat form login yang lebih aman.

  1. Membuat table users
  2. Membuat file untuk validasi akses
  3. Membuat form login
  4. Membuat file untuk logout
  5. Form untuk tambah user (bonus)

Membuat Table Users

Buatlah tabel users untuk dengan struktur seperti di bawah (bisa menggunakan phpMyAdmin atau yang lain).

Kolom Tipe Data Keterangan
id integer primary key, auto increment
username varchar unique
password varchar
salt varchar karakter acak untuk perkuat password
aktif tinyint 1 = user aktif, 0 tidak aktif
nama varchar

Kolom lain bisa ditambahkan sesuai dengan kebutuhan

Mebuat file untuk validasi akses

Buatlah file cek-akses.php yang akan digunakan untuk validasi akses user. Apakah sudah login atau tidak. Variable $_SERVER (selengkapnya lilhat di https://php.net/$SERVER) akan digunakan untuk memvalidasi siapa browser dan alamat IP yang digunakan user. Jika browser dan alamat IP berubah makan user harus login lagi.

<?php
session_start();
if(!isset($_SESSION['browser']) || !isset($_SESSION['ip']) || empty($_SESSION['user'])) {
    header("Location: login.php");
    exit;
}

if ($_SESSION['browser'] != md5($_SERVER['HTTP_USER_AGENT']) || $_SESSION['ip'] != $_SERVER['REMOTE_ADDR']) {
    header("Location: login.php");
    exit;
}

Paling pertama yang harus dilakukan adalah memulai session dengan fungsi session_start(). Kemudian jika tidak ada informasi browser, IP atau user di session arahkan user ke halaman login. Selanjutnya cek apakah informasi browser yang disimpan di session sama dengan $_SERVER['HTTP_USER_AGENT'] dan alamat IP sama dengan $_SERVER['REMOTE_ADDR']. Jika misalnya cookie dicuri, maka tidak akan bisa digunakan karena alamat IP pencuri pasti berbeda. Kemudian file ini bisa di-include di file yang harus diakses setelah login seperti di bawah.

<?php
include_once "cek-akses.php";
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Admin</title>
        <style>
            table {
                border: 1px solid #ddd;
                border-collapse: collapse;
                width: 50%;
            }

            table td, table th {
                border: 1px solid #ddd;
                padding: 8px
            }
        </style>
    </head>
    <body>
        <h1>Selamat Datang</h1>
        <p>
        <a href="tambah-user.php">Tambah User</a> | <a href="logout.php">Logout</a>
        </p>
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Nama</th>
                    <th>Aktif</th>
                </tr>
            </thead>
            <tbody>
                <?php
                $pdo = include "koneksi.php";
                $query = $pdo->prepare("select id,nama,aktif from users");
                $query->execute();
                while($user = $query->fetch()) {
                ?>
                <tr>
                    <td><?php echo $user['id'];?></td>
                    <td><?php echo $user['nama'];?></td>
                    <td><?php echo $user['aktif'];?></td>
                </tr>
                <?php }?>
            </tbody>
        </table>
    </body>
</html>

Membuat Form Login

Sekarang buatlah file login.php dan buat html form login seperti di bawah, dengan 2 input username dan password

<!DOCTYPE html>
<html>
    <head>
        <title>Login</title>
    </head>
    <body>
        <h1>Please login</h1>
        <?php
        if ($gagal) {
            echo '<h2 style="color:red">Username atau password salah</h2>';
        }
        ?>
        <form method="POST" action="">
            <div>
                <div>Username</div>
                <p>
                    <input type="text" name="username"/>
                </p>
            </div>
            <div>
                <div>Password</div>
                <p>
                    <input type="password" name="password"/>
                </p>
            </div>
            <button type="submit">Login</button>
        </form>
    </body>
</html>

Kemudian di bagian paling atas file tambahkan kode php untuk membuat validasi password user.

<?php
session_start();
$gagal = false;
if(!empty($_POST)) {
    $pdo = include "koneksi.php";
    $query = $pdo->prepare("select * from users where username=:username");
    $query->execute(array('username' => $_POST['username']));
    $user = $query->fetch();
    if (!$user) {
        $gagal = true;
    } elseif($user['aktif'] != 1 || $user['password'] != sha1($_POST['password'].$user['salt'])){
        $gagal = true;
    } else {
        $_SESSION['browser'] = md5($_SERVER['HTTP_USER_AGENT']);
        $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
        $_SESSION['user'] = array(
            'id' => $user['id'],
            'nama' => $user['nama']
        );
        header("Location: admin.php");
        exit;
    }
}
?>

Kembali paling atas mulai session dengan session_start(). Kemudian jika user mencoba login dengan mengklik tombol login, buat koneksi ke database dengan. File koneksi.php untuk membuat koneksi ke datatabase seperti kode di bawah. Di baris ke-6 sampai ke-8 kita cari data user dengan username yang telah dimasukkan user. Jika tidak tidak ditemukan (baris ke-9), set $gagal dengan true. Begitu juga jika user tidak aktif, atau password tidak sama dengan yang di database. Perhatikan baris ke-11.
$user['password'] != sha1($_POST['password'].$user['salt']) password yang di input user digabungkan dengan data salt dari database (lebih lengkah penjelasaany di bawah di form tambah user). Terakhir jika password benar dan user aktif maka simpan informasi browser, IP dan user ke session.

<?php
// file koneksi.hp
$host = "mysql";
$username = "root";
$password = "change_me";
$database = "tutorials";

return new PDO("mysql:host=$host;dbname=$database", $username, $password, array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));

Membuat Logout

Setelah berhasil login maka user harus bisa logout. Membuat logout lebih sederhana yaitu dengan menghapus semua informasi session yang telah dibuat di form login seperti kode php di bawah dalam file logout.php.

<?php
session_start();
unset($_SESSION['browser']);
unset($_SESSION['ip']);
unset($_SESSION['user']);
session_regenerate_id();
session_destroy();

header("Location: login.php");

Baris ke-6 digunakan untuk membuat ID session yang baru agar ID yang lama tidak bisa digunakan lagi. Dan baris ke-7 untuk membuang session yang sebelumnya.

Form Untuk Tambah User

Pertama tama buatlah file tambah-user.php dan tambahkan form untuk tambah user seperti di bawah.

<!DOCTYPE html>
<html>
    <head>
        <title>Tambah User</title>
    </head>
    <body>
        <h1>Tambah User</h1>
        <?php
        if ($error) {
        echo '<h5 style="color:red">'.$error.'</h5>';
        }
        ?>
        <form method="POST" action="">
            <div>
                <div>Nama</div>
                <p>
                    <input type="text" name="nama"/>
                </p>
            </div>
            <div>
                <div>Username</div>
                <p>
                    <input type="text" name="username"/>
                </p>
            </div>
            <div>
                <div>Password</div>
                <p>
                    <input type="password" name="password"/>
                </p>
            </div>
            <div>
                <div>Ulang Password</div>
                <p>
                    <input type="password" name="password2"/>
                </p>
            </div>
            <div>
                <div>Aktif</div>
                <p>
                    <input type="hidden" name="aktif" value="0"/>
                    <input type="checkbox" name="aktif" value="1"/>
                </p>
            </div>
            <button type="submit">Simpan</button>
        </form>
    </body>
</html>

Setelah itu tambahkan kode php untuk menambah user di bagian paling atas seperti di bawah.

<?php
include_once "cek-akses.php";
$error = '';
if (!empty($_POST)) {
    if($_POST['password2'] != $_POST['password']) {
        $error = 'Password dan ulang password harus sama';
    } else {
        try {
            $pdo = include "koneksi.php";
            $query = $pdo->prepare("insert into users (username, password, salt, nama, aktif) values(:username, :password,:salt,:nama,:aktif)");
            $string = str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
            $salt = sha1(substr($string, 0, 8).time().rand());
            $query->execute(array(
                'username' => $_POST['username'],
                'password' => sha1($_POST['password'].$salt),
                'salt' => $salt,
                'nama' => $_POST['nama'],
                'aktif' => $_POST['aktif']
            ));
            header("Location: admin.php");
            exit;
        } catch (Exception $e) {
            $error = $e->getMessage();
        }
    }
}
?>

Baris 5-7 kita lakukan validasi password dan ulang password harus sama. Di baris 11-12 kita membuat nilai salt menggunakan fungsi str_shuffle, time dan juga rand agar mendapatkan karakter acak yang lebih baik. Baris 13-19 digunakan untuk menyimpan data user. Perhatikan baris ke-15, 'password' => sha1($_POST['password'].$salt). Password disimpan dengan gabungan dengan password yang diisi oleh user dan juga salt dengan begitu password yang tersimpan di database tidak pernah sama. Walaupun user input data yang sama. Password juga disimpan dalam bentuk SHA1 sehingga tidak bisa dilihat dengan kasat mata. Dengan 2 kombinasi itu password akan susah ditebak seandainya database berhasil dicuri.

Kesimpulan

Dalam tutorial php membuat form login yang lebih aman ini telah dijelaskan cara untuk menangkal pencurian cookie, dengan memvalidasi browser dan alaman IP user. Kemudian password disimpan menggunakan SHA1 sehingga tidak bisa dilihat dengan kasat mata. Password juga dikombinasikan dengan salt nilai acak yang membuat password yang disimpan di database tidak pernah sama walaupun user memasukkan password yang sama. Sehingga jika terjadi pencurian database password akan sudah ditebak. Perlu dicatat bahwa cara ini tidak benar benar 100% memberi jaminan keamanan. SHA1 dapat dipecahkan menggunakan super komputer. Untuk mengingkatkannya bisa menggunakan bcrypt namun lebih lambat dari pada SHA1. Pastikan juga website anda tidak memiliki masalah XSS. Sehingga cookie tidak mudah dicuri. Ikuti recomendasi dari setting cookie di php. Minimal set cookie SameSite=Lax httponly secure dan gunakan SSL di website Anda.