Membuat login remember me dengan PHP
Posted: 16 May 2016, Last updated: 30 Sep 2018
Sistem login yang Saya bahas di sini disadur dari sistem login pada framework Laravel. Sistem ini menggunakan session dan cookie untuk memproses login. Pertama-tama, mari kita buat form login:
Membuat Form login dengan HTML
File login.php
<html> <head><title>Halaman login</title></head> <body> <form method="post" action=""> <table> <tr><td>Username:</td><td><input type="text" name="username" /></td></tr> <tr><td>Password:</td><td><input type="password" name="password" /></td></tr> <tr><td></td><td><input type="checkbox" name="remember" checked /> Remember me</td></tr> <tr><td colspan="2"><button name="login" type="submit">Masuk!</button></td></tr> </table> </form> </body> </html>
Dengan menggunakan form, table dan input HTML, kita telah membuat sebuah antarmuka untuk login.
Membaca POST dari HTML dengan PHP
Berikutnya, kita coba mengambil kiriman data dari HTML tersebut dengan POST pada PHP, masih pada file login.php
:
<?php if (isset($_POST['login'])) { echo "<pre>".print_r($_POST, true)."</pre>"; die(); } ?><html> ... </html>
Pastikan jika Anda menginput form tersebut, tampil sesuatu seperti berikut:
Array ( [username] => fandi [password] => 123123 [remember] => 1 [login] => )
Membuat database login
Untuk uji coba ini, kita perlu membuat database untuk menampung data pengguna. Syntax database ini sengaja tidak menggunakan AUTO_INCREMENT pada MySQL ataupun SERIAL pada PostgreSQL agar script ini bisa dicoba oleh semua. Jalankan perintah berikut pada database:
CREATE DATABASE coba;
Pindah ke database coba: USE coba;
pada MySQL atau \c coba
pada PostgreSQL. Dan tentunya Anda juga boleh menggunakan GUI pada phpMyAdmin atau phpPgAdmin.
CREATE TABLE login ( id INT, username VARCHAR(100) NOT NULL, password VARCHAR(100) NOT NULL, remember_token VARCHAR(100), remember_expiry INT, CONSTRAINT pk_login PRIMARY KEY (id), CONSTRAINT uq_username_login UNIQUE (username) ); CREATE INDEX idx_remember_login ON login (remember_token);
Koneksi ke database dengan PHP
Untuk berinteraksi dengan database melalui PHP, kita akan menggunakan class PDO. Buat script nyambung.php
:
<?php list($host, $db, $user, $pass, $port) = ["localhost","coba","fandi", "123", 5432]; $pdo = new \PDO( "pgsql:host=$host;port=$port;dbname=$db;", $user, $pass, array( \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_OBJ ));
Untuk koneksi ke MySQL, Anda dapat menyesuaikan kode di atas seperti pada tutorial koneksi PDO.
Mengisi data ke dalam tabel login
Kita tidak membahas register pengguna di sini, jadi kita langsung saja insert beberapa data ke dalam tabel login. Kita menggunakan script PHP isidata.php
:
<?php include "nyambung.php"; $stmt = $pdo->query("SELECT COUNT(*) FROM login"); $baris = $stmt->fetch(); if ($baris->count > 0) { //kolom count dari query echo "Data login telah ada"; die(); } //class Login class Login { public $id, $username, $password; public function __construct($arr) { foreach ($arr as $k=>$v) $this->$k = $v; } } //data-data login $logins = [ new Login(["id"=>1, "username"=>"user1", "password"=>hash('haval256,4','123')]), new Login(["id"=>2, "username"=>"user2", "password"=>hash('haval256,4','456')]), new Login(["id"=>3, "username"=>"user3", "password"=>hash('haval256,4','789')]), ]; //insert ke database try { $stmt = $pdo->prepare("INSERT INTO login VALUES (:id,:username,:password, null, 0)"); foreach ($logins as $objLogin) $stmt->execute((array)$objLogin); } catch (Exception $ex) { echo $ex->getMessage(); throw $ex; } echo "Insert berhasil";
Tentunya Anda perlu mengunjungi localhost/folder/coba/anda/isidata.php lewat browser agar data tersebut terisi.
Melakukan login
Sekarang mari kita membuat script untuk menerima login. Kita buat juga class.Login.php
agar script kita lebih rapi.
<?php class Login { public $id, $username, $password, $remember_token, $remember_expiry; public function __construct($arr) { foreach ($arr as $k=>$v) $this->$k = $v; } static function findByUsername($username) { include "nyambung.php"; $stmt = $pdo->prepare("SELECT * FROM login WHERE username=:user"); $stmt->execute(["user"=>$username]); $baris = $stmt->fetch(); if ($baris != null) return new Login($baris); return null; } }
Kemudian kita gunakan dalam script login.php
yang tadi:
<?php session_start(); if (isset($_POST['login'])) { include "class.Login.php"; $objLogin = Login::findByUsername($_POST['username']); if (!$objLogin) { echo "User tidak dikenal"; die(); } elseif ($objLogin->password != hash("haval256,4",$_POST['password'])) { echo "Password salah"; die(); } die("Login berhasil"); } ?><html> ... </html>
Tentunya bagian dalam <html> tidak berubah. Jika sudah berhasil, kita tambahkan lebih lanjut proses loginnya: menyimpan ke dalam session dan pindah ke halaman home. Ubah baris die("Login berhasil");
menjadi:
$objLogin->login(); header("location:/home.php");
Lalu tambahkan method login di dalam class.Login.php
:
public function login() { $_SESSION['login'] = $this; }
Sampai di sana, Anda sudah dapat melakukan login. Bila user dan pass benar, maka script akan diarahkan ke home.php.
Menambahkan fitur remember me pada login
Kita perlu menambahkan pengecekan input pada checkbox remember. Tambahkan di bagian atas $objLogin->login();
pada login.php
:
if (isset($_POST['remember']) && $_POST['remember'] == 'on') { $objLogin->login(time() + 3600 * 24 * 14); } else $objLogin->login(); header("location:/home.php");
Dan update method login pada class.Login.php
:
public function login($expiry=0) { if ($expiry>0) { $token = hash('ripemd256',time()); setcookie("login",$token,$expiry); $this->remember_token = $token; $this->remember_expiry = $expiry; } else { $this->remember_token = ''; $this->remember_expiry = 0; } //update ke database include "nyambung.php"; try { $sql = "UPDATE login SET remember_token=:token, remember_expiry=:expiry WHERE id=:id"; $stmt = $pdo->prepare($sql); $stmt->bindParam("token",$this->remember_token); $stmt->bindParam("expiry",$this->remember_expiry); $stmt->bindParam("id",$this->id); $stmt->execute(); } catch (Exception $ex) { echo $ex->getMessage(); die(); } $_SESSION['login'] = $this; }
Method tersebut akan membuat dan menyimpan token remember me ke dalam database. Tetapi bila user melakukan login tanpa mencentang "remember", token akan dihapus. Sedangkan tampak luar program, masih sama seperti sebelumnya. Login seperti biasa.
Login dengan cookie tanpa session
Sebelum melanjutkan, Anda mungkin tertarik untuk membaca tentang cookie pada PHP. Dan ada baiknya kita buat dulu script home.php
:
<?php include "class.Login.php"; session_start(); if (isset($_SESSION['login'])) { echo "Selamat datang ".$_SESSION['login']->username; } else { echo "Anda belum login"; }
Untuk mencoba login dengan cookie saja, kita perlu mencoba menghapus session untuk mengemulasi session yang telah expired. Kita coba membuat logout.php
:
<?php include "class.Login.php"; session_start(); if ($_GET['tipe'] == "session") { //hapus session saja unset ($_SESSION['login']); } else { //hapus session dan cookie unset ($_SESSION['login']); setcookie("login",'',time()-1); } header("location:/home.php");
Kita coba hapus session dengan mengunjungi localhost/logout.php?tipe=session
. Kita akan diarahkan kembali ke halaman home dengan pesan "Anda belum login". Sekarang kita coba login menggunakan cookie. Tambahkan method findByToken di class.Login.php
:
static function findByToken($rememberToken) { include "nyambung.php"; $stmt = $pdo->prepare("SELECT * FROM login WHERE remember_token=:token"); $stmt->execute(["token"=>$rememberToken]); $baris = $stmt->fetch(); if ($baris != null) return new Login($baris); return null; }
Lalu pada bagian echo "Anda belum login";
di home.php
, ubah menjadi:
echo "Anda belum login"; if (isset($_COOKIE['login'])) { $objLogin = Login::findByToken($_COOKIE['login']); if ($objLogin == null) echo "Cookie login tidak valid"; else { echo "<br />Berhasil login dengan cookie: <b>$objLogin->username</b>"; $objLogin->login(time()+3600*24*14); } }
Jika setelah logout muncul tulisan seperti:
Anda belum login Berhasil login dengan cookie: user2
Berarti Anda telah berhasil melakukannya. Source code lengkap tutorial ini dapat didownload di SINI.