Skip to main content

Membuat Script Login yang Aman dengan PHP dan MySQL

Sebuah aplikasi berbasis web umumnya membutuhkan halaman login bagi user/member untuk mengakses halaman tertentu. Halaman itu tentunya harus aman dari resiko pembobolan dan pencurian data.
Kali ini saya akan mencoba memberikan sedikit tips cara membuat script login yang aman dengan PHP dan MySQL.
Script ini hanya memberikan gambaran tentang bagaimana cara mengamankan halaman login dari ancaman dan resiko pembobolan dan pencurian data user/member. Script ini juga menggunakan teknik enkripsi password dengan fungsi hash(sha512) dan salt.
Saya tidak meng-klaim script ini benar-benar dapat membuat halaman login yang aman karena masalah keamanan system web tentu lebih luas dan kompleks.
Semoga tips berikut ini bisa menambah pengetahuan Anda dalam mengamankan aplikasi web Anda.
Script Login berikut ini diharapkan dapat menahan halaman web Anda dari serangan:
•SQL Injections
•Session Hijacking
•Network Sniffing
•Cross Site Scripting
•Brute Force Attacks
Script ini jalan di PHP minimal versi 5.4 dan MySQL versi 5.0
Pertama kita siapkan databasenya.
1. Create Database login:
CREATE DATABASE `login`;
2. Create user untuk akses database tersebut. Hindari menggunakan user default root MySql.
CREATE USER 'admin_db'@'localhost' IDENTIFIED BY 'eKcGZr59zAa2BEWU';
GRANT SELECT, INSERT, UPDATE ON `login`.* TO 'sec_user'@'localhost';
3. Create tabel login_attempts untuk menyimpan data percobaan login oleh user. Dengan demikian kita bisa menahan serangan brute force attack


CREATE TABLE `login_attempts` (
    `user_id` INT(11) NOT NULL,
    `time` VARCHAR(30) NOT NULL
) ENGINE=InnoDB
4. Create tabel members dengan 5 field: id, username, email, password dan salt.
Khusus pada field password kita gunakan tipe CHAR(128) untuk menyimpan data password yang di encrypt dengan fungsi hash(sha512) dan salt .


CREATE TABLE `secure_login`.`members` (
    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `username` VARCHAR(30) NOT NULL,
    `email` VARCHAR(50) NOT NULL,
    `password` CHAR(128) NOT NULL,
    `salt` CHAR(128) NOT NULL
) ENGINE = InnoDB;
5. Insert 1 row data user admin ke tabel members untuk test login.


INSERT INTO `login`.`members` VALUES(1, 'admin_user', 'admin@kampushendra.com',
'00807432eae173f652f2064bdca1b61b290b52d40e429a7d295d76a71084aa96c0233b82f1feac45529e0726559645acaed6f3ae58a286b9f075916ebf66cacc',
'f9aab579fc1b41ed0c44fe4ecdbfcdb4cb99b9023abb241a6db833288f4eea3c02f76e0d35204a8695077dcf81932aa59006423976224be0390395bae152d4ef');
Berikutnya kita siapkan script PHP-nya.
1. Create folder “includes” di luar folder root aplikasi web Anda (misal: xampp/apps/includes/)
2. Create file psl-config.php berikut ini lalu simpan di folder includes:
<?php
/** These are the database login details */ 
define("HOST", "localhost");    // The host you want to connect to.
define("USER", "admin_db");    // The database username.
define("PASSWORD", "eKcGZr59zAa2BEWU");  // The database password.
define("DATABASE", "login");     // The database name.
define("CAN_REGISTER", "any");
define("DEFAULT_ROLE", "member");
define("SECURE", FALSE);    // FALSE for Dev, TRUE for Prod using https
?>
3. Create file db_connect.php berikut ini lalu simpan di folder includes:
<?php
include_once 'psl-config.php';   // As functions.php is not included
$mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
?>
4. Create file functions.php berikut ini lalu simpan di folder includes:
<?php
include_once 'psl-config.php';
function sec_session_start() {
    $session_name = 'sec_session_id';   // Set a custom session name
    $secure = SECURE;
    // This stops JavaScript being able to access the session id.
    $httponly = true;
    // Forces sessions to only use cookies.
    if (ini_set('session.use_only_cookies', 1) === FALSE) {
        header("Location: ../error.php?err=Could not initiate a safe session (ini_set)");
        exit();
    }
    // Gets current cookies params.
    $cookieParams = session_get_cookie_params();
    session_set_cookie_params($cookieParams["lifetime"],
        $cookieParams["path"], 
        $cookieParams["domain"], 
        $secure,
        $httponly);
    // Sets the session name to the one set above.
    session_name($session_name);
    session_start();              // Start the PHP session 
    session_regenerate_id(true);  // regenerated the session, delete the old one. 
}
//This login function will check the email and password against the database. 
//It will return true if there is a match.
function login($email, $password, $mysqli) {
    // Using prepared statements means that SQL injection is not possible. 
    if ($stmt = $mysqli->prepare("SELECT id, username, password, salt 
        FROM members  WHERE email = ?  LIMIT 1")) {
        $stmt->bind_param('s', $email);  // Bind "$email" to parameter.
        $stmt->execute();    // Execute the prepared query.
        $stmt->store_result();
        // get variables from result.
        $stmt->bind_result($user_id, $username, $db_password, $salt);
        $stmt->fetch();
        // hash the password with the unique salt.
        $password = hash('sha512', $password . $salt);
        if ($stmt->num_rows == 1) {
            // If the user exists we check if the account is locked
            // from too many login attempts 
            if (checkbrute($user_id, $mysqli) == true) {
                // Account is locked 
                // Send an email to user saying their account is locked
                return false;
            } else {
                // Check if the password in the database matches
                // the password the user submitted.
                if ($db_password == $password) {
                    // Password is correct!
                    // Get the user-agent string of the user.
                    $user_browser = $_SERVER['HTTP_USER_AGENT'];
                    // XSS protection as we might print this value
                    $user_id = preg_replace("/[^0-9]+/", "", $user_id);
                    $_SESSION['user_id'] = $user_id;
                    // XSS protection as we might print this value
                    $username = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $username);
                    $_SESSION['username'] = $username;
                    $_SESSION['login_string'] = hash('sha512', $password . $user_browser)
                    // Login successful.
                    return true;
                } else {
                    // Password is not correct
                    // We record this attempt in the database
                    $now = time();
                    $mysqli->query("INSERT INTO login_attempts(user_id, time) VALUES ('$user_id', '$now')");
                    return false;
                }
            }
        } else {
            // No user exists.
            return false;
        }
    }
}
//This checkbrute function will hold login tries for 2 hour if 5 logins failed.
function checkbrute($user_id, $mysqli) {
    // Get timestamp of current time 
    $now = time();
     // All login attempts are counted from the past 2 hours. 
    $valid_attempts = $now - (2 * 60 * 60);
     if ($stmt = $mysqli->prepare("SELECT time FROM login_attempts WHERE user_id = ? AND time > '$valid_attempts'")) {
        $stmt->bind_param('i', $user_id);
         // Execute the prepared query. 
        $stmt->execute();
        $stmt->store_result();
         // If there have been more than 5 failed logins 
        if ($stmt->num_rows > 5) {
            return true;
        } else {
            return false;
        }
    }
}
//This login_check function will Check if all session variables are set
function login_check($mysqli) {
    if (isset($_SESSION['user_id'], $_SESSION['username'], $_SESSION['login_string'])) {
        $user_id = $_SESSION['user_id'];
        $login_string = $_SESSION['login_string'];
        $username = $_SESSION['username'];
         // Get the user-agent string of the user.
        $user_browser = $_SERVER['HTTP_USER_AGENT'];
         if ($stmt = $mysqli->prepare("SELECT password FROM members WHERE id = ? LIMIT 1")) {
            // Bind "$user_id" to parameter. 
            $stmt->bind_param('i', $user_id);
            $stmt->execute();   // Execute the prepared query.
            $stmt->store_result();
             if ($stmt->num_rows == 1) {
                // If the user exists get variables from result.
                $stmt->bind_result($password);
                $stmt->fetch();
                $login_check = hash('sha512', $password . $user_browser);
                if ($login_check == $login_string) {
                    // Logged In!!!! 
                    return true;
                } else {
                    // Not logged in 
                    return false;
                }
            } else {
                // Not logged in 
                return false;
            }
        } else {
            // Not logged in 
            return false;
        }
    } else {
        // Not logged in 
        return false;
    }
}
//This login_check function will sanitizes URL from the PHP_SELF server variable
function esc_url($url) {
     if ('' == $url) {
        return $url;
    }
    $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
    $strip = array('%0d', '%0a', '%0D', '%0A');
    $url = (string) $url;
     $count = 1;
    while ($count) {
        $url = str_replace($strip, '', $url, $count);
    }
    $url = str_replace(';//', '://', $url);
    $url = htmlentities($url);
    $url = str_replace('&amp;', '&', $url);
    $url = str_replace("'", ''', $url);
    if ($url[0] !== '/') {
        // We're only interested in relative links from $_SERVER['PHP_SELF']
        return '';
    } else {
        return $url;
    }
}
?>
5. Create file process_login.php berikut ini lalu simpan di folder aplikasi web Anda (Misal: //xampp/htdocs/myweb/)
<?php
include_once 'db_connect.php';
include_once 'functions.php';
sec_session_start(); // custom secure way of starting a PHP session.
if (isset($_POST['email'], $_POST['p'])) {
    $email = $_POST['email'];
    $password = $_POST['p']; // The hashed password.
    if (login($email, $password, $mysqli) == true) {
        // Login success 
        header('Location: ../protected_page.php');
    } else {
        // Login failed 
        header('Location: ../index.php?error=1');
    }
} else {
    // The correct POST variables were not sent to this page. 
    echo 'Invalid Request';
}
?>
6. Create file logout.php berikut ini lalu simpan di folder aplikasi web Anda (Misal: //xampp/htdocs/myweb/)
<?php
include_once 'functions.php';
sec_session_start();
// Unset all session values 
$_SESSION = array();
// get session parameters 
$params = session_get_cookie_params();
// Delete the actual cookie. 
setcookie(session_name(),'', time() - 42000,
        $params["path"], 
        $params["domain"], 
        $params["secure"], 
        $params["httponly"]);
// Destroy session 
session_destroy();
header('Location: ../index.php');
?>
7. Create file index.php berikut ini lalu simpan di folder aplikasi web Anda (Misal: //xampp/htdocs/myweb/)
File index.php adalah halaman login Anda.
<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';
sec_session_start();
if (login_check($mysqli) == true) {
    $logged = 'in';
} else {
    $logged = 'out';
}
?>
<!DOCTYPE html>
<html>
<head>
    <title>Secure Login: Log In</title>
    <script type="text/JavaScript" src="js/sha512.js"></script> 
    <script type="text/JavaScript" src="js/forms.js"></script> 
</head>
<body>
        <?php
        if (isset($_GET['error'])) {
            if(@$_SESSION['error']==2)
        echo '<p class="error">Account is locked due to 5 failed logins!</p>';
        else
        echo '<p class="error">Error Logging In!</p>';
        }
        ?> 
        <form action="includes/process_login.php" method="post" name="login_form">                      
            Email: <input type="text" name="email" />
            Password: <input type="password" name="password" id="password"/>
            <input type="button" value="Login" onclick="formhash(this.form, this.form.password);" /> 
        </form>
		<?php
        if (login_check($mysqli) == true) {
            echo '<p>Currently logged ' . $logged . ' as ' . htmlentities($_SESSION['username']) . '.</p>';
            echo '<p>Do you want to change user? <a href="includes/logout.php">Log out</a>.</p>';
        } else {
            echo '<p>Currently logged ' . $logged . '.</p>';
            echo "<p>If you don't have a login, please <a href='register.php'>register</a></p>";
                
		}
?>
</body>
</html>
8. Create file protected_page.php berikut ini lalu simpan di folder aplikasi web Anda
File protected_page.php adalah halaman member yang bisa diakses setelah berhasil login.
<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';
sec_session_start(); 
if(login_check($mysqli) == false) {
    echo 'You are not authorized to access this page, please login.';
    exit();
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Secure Login: Protected Page</title>
        <link rel="stylesheet" href="styles/main.css" />
    </head>
    <body>
        <?php if (login_check($mysqli) == true) : ?>
            <p>Welcome <?php echo htmlentities($_SESSION['username']); ?>!</p>
            <p>
                This is an example protected page.  To access this page, users
                must be logged in.  At some stage, we'll also check the role of
                the user, so pages will be able to determine the type of user
                authorised to access the page.
            </p>
            <p>Return to <a href="index.php">login page</a></p>
        <?php else : ?>
            <p>
               <span class="error">You are not authorized to access this page.</span> Please <a href="index.php">login</a>.
            </p>
        <?php endif; ?>
    </body>
</html>
9. Create folder js di dalam folder aplikasi web Anda (Misal: //xampp/htdocs/myweb/js/)
10. Download file sha512.js dan forms.js lalu simpan di folder js
Setelah semua file siap, Anda dapat mencoba script login ini di web browser Anda.

Comments

Popular posts from this blog

Membuat Tombol Scroll ke Atas (back to top) dengan JQuery

Cara membuat tombol scroll ke atas dengan jquery (back to top) – Sebuah website yang begitu panjang kebawah tentu akan menyulitkan penggunanya untuk bisa kembali lagi keatas, karena harus scroll terus dengan menggunakan mouse. Hal tersebut tentu kurang efektif. Untuk mengatasi hal tersebut, banyak orang menggunakan sebuah tombol yang ketika di klik akan membawa kita ke bagian atas halaman website dengan animasi yang menarik. Dibutuhkan jquery untuk membuat hal semacam itu, dan pada tutorial kali ini  Media Kunci  akan mengajarkan Anda cara membuatnya. Mudah kok, script nya juga tidak panjang. 1.  HTML:  Buat sebuah file html dan tuliskan script markup nya seperti berikut ini <div id="wrapper"> <h1>Membuat Tombol Scroll to Top Dengan Jquery</h1> <h5><a href="https://mediakunci.blogspot.com/2019/04/membuat-tombol-scroll-ke-atas-back-to.html">Baca tutorial di Media Kunci</a></h5> Konten yang panjang disini....

Insert Data ke Database Tanpa Loading dengan PHP dan jQuery

Insert Data ke Database Tanpa Loading dengan PHP dan jQuery. Tutorial pertama tentang jQuery ini akan saya mulai dari yang sederhana aja dulu yaitu cara Insert Data ke Database Tanpa Loading dengan PHP dan jQuery. Baca juga :  Menampilkan Data dari Database MySQL Tanpa Loading Dengan jQuery Sebelumnya silahkan download dahulu jQuery di website resminya  disini . Selanjutnya buat sebuah database, dalam hal ini saya membuat database dengan nama  terserah . Kemudian dumping Script SQL di bawah ini: CREATE TABLE `siswa` ( `nama` varchar(32) NOT NULL, `kelas` varchar(3) NOT NULL, `jurusan` varchar(20) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; Dari Script SQL di atas anda akan mendapatkan sebuah table dengan nama  siswa  dengan tiga buah field yaitu nama, kelas, jurusan. Jika sudah kita akan membuat Form HTML, dan berikut ini kodenya: <html> <head> <title>Insert Data ke Database Dengan jQuery</title> </head> <body> <form id=&q

Belajar PHP (Membuat Halaman Komentar)

Fasilitas komentar pada sebuah website akan menjadikan situs kita rancang menjadi lebih hidup karena dapat mengajak pengunjung untuk berinteraksi secara langsung. Umumnya fasilitas komentar dapat kita jumpai hampir disetiap website, blog atau bahkan forum seperti ini untuk mendapatkan umpan balik baik itu masukan, kritikan, pertanyaan atau bahkan pujian dari pengunjung website. Konsep pembuatan komentar ternyata cukup sederhana, asalkan paham sedikit mengenai PHP dan MYSQL, Insya Allah kamu dapat memahami bagaimana cara kerjanya. Berikut ini saya akan mencoba menulis bagaimana membuat fasilitas halaman komentar sederhana Masuk ke MYSQL buat database dan tabel dalam contoh ini databasenya adalah komentar sedangkan tabelnya adalah data. mysql> use komentar; Database changed mysql> mysql> use komentar; Database changed mysql> create table data( -> id INT NOT NULL  AUTO_INCREMENT PRIMARY KEY, -> nama VARCHAR(50) NOT NULL, -> email VARCHAR(50) NOT NULL, -> isi TEXT