Category Archives: MySQL

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('&', '&', $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.

Untuk script selengkapnya bisa Anda download dari sumber berikut ini:
https://github.com/peredurabefrog/phpSecureLogin

Export Data MySQL ke Excel .csv

Pada Aplikasi Web Database biasanya kita memerlukan fasilitas untuk export atau download data dari database MySQL ke Excel.

Kali ini saya akan berikan contoh coding PHP untuk membuat fasilitas export data MySQL ke dalam file .csv yang dapat dibuka dengan program Excel.

Contoh coding PHP berikut ini untuk mendownload data pada tabel “users di database “students”, berikut ini coding selengkapnya.

<?php
error_reporting(0);
date_default_timezone_set('Asia/Jakarta');
$Timestamp = date('Ymd@His');
// Connect to DB
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = '';
$dbname = 'students';
$tbl	= 'users';
$filename = "$tbl"."_"."$Timestamp".".csv";
$conn = mysqli_connect($dbhost, $dbuser, $dbpass,$dbname) or die ('Error connecting to db!');
// Get all fields names in the table.
$result = mysqli_query($conn,"SHOW COLUMNS FROM $tbl") or die("Error running query!");
$numofcol = mysqli_num_rows($result);
$out = '';
if ($numofcol > 0)
{   while ($row = mysqli_fetch_assoc($result))
	{	$out .='"'.$row['Field'].'",'; }
}
$out .="\n";
// Add all records in the table to $out.
$result=mysqli_query($conn,"SELECT * FROM $tbl") or die("Error run query");
while ($l = mysqli_fetch_array($result))
{	for ($i = 0; $i < $numofcol; $i++)
	{	$out .='"'.$l["$i"].'",'; }
	$out .="\n";
}
//Download $filename.csv
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment;filename=$filename");
header("Content-Transfer-Encoding: binary ");
echo $out;
//or save $out as $filename.csv on server
//file_put_contents($filename, $out);
?>

Jika Anda ingin menyimpan file csv di server, Anda tinggal membuka comment pada 2 baris terakhir.

Selamat mencoba, semoga sukses.

Cara Akses Database MySQL dengan PHP

Pada tulisan saya sebelumnya saya telah memberikan cara membuat database web dengan mysql. Jadi saya asumsikan Anda sudah memiliki database “login_student” dan “table_login_student”. Kali ini saya akan berikan coding PHP untuk mengakses database MySQL tersebut.

1. Membuat Koneksi PHP ke MySQL
Ketiklah coding PHP di bawah ini dengan notepad (atau notepad++) lalu simpan dengan nama file “config.php”

<?php
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "";
$dbname = "login_student";
$conn = mysqli_connect($dbhost, $dbuser, $dbpass,$dbname) 
        or die ('Error connecting to mysql');
?>

2. Membuat Form Insert Data
Ketiklah coding PHP di bawah ini dengan notepad (atau notepad++) lalu simpan dengan nama file “insert.php”

<html>
<head>
<title>Tambah Data</title>
</head>
<body>
<?php
if(isset($_POST['save']))
{  include 'config.php';
   extract($_REQUEST);
   $query=mysqli_query($conn,"insert into tabel_login_student
          SET username='$username', password='$password', level='$level',
          fullname='$fullname', email='$email', Telp='$Telp'")
          or die(mysqli_error($conn));
   if($query)
   {  echo "Data telah tersimpan.";
   }
}
?>
<form action='#' method='post' border='0'>
<table>
<tr><td>Username</td><td><input type='text' name='username' /></td>
</tr>
<tr><td>Password</td><td><input type='text' name='password' /></td>
</tr>
<tr><td>Level</td><td><input type='text' name='level' /></td>
</tr>
<tr><td>Fullname</td><td><input type='text' name='fullname' /></td>
</tr>
<tr><td>Email</td><td><input type='text' name='email' /></td>
</tr>
<tr><td>Telp</td><td><input type='text' name='Telp' /></td>
</tr>
<tr><td></td><td><input type='submit' value='Save' name="save" /></td>
</tr>
</table>
</form>
</body>
</html>

3. Menampilkan Data
Ketiklah coding PHP di bawah ini dengan notepad (atau notepad++) lalu simpan dengan nama file “show_data.php”

<?php
   include 'config.php';
   $sql="select * from tabel_login_student";
   $rs=mysqli_query($conn,$sql) or die($sql.">>".mysqli_error($conn));
   $num=mysqli_num_rows($rs);
   if($num>0){ //check if more than 0 record found
?>
<table border='1'>
<tr>
  <th>Username</th><th>Password</th><th>Level</th><th>Fullname</th><th>Email</th><th>Telp</th>
</tr>
<?php
  while($row=mysqli_fetch_array($rs))
  {  extract($row);
?>
<tr>
  <td><?php echo $username; ?></td>
  <td><?php echo $password; ?></td>
  <td><?php echo $level; ?></td> 
  <td><?php echo $fullname; ?></td>
  <td><?php echo $email; ?></td>
  <td><?php echo $Telp; ?></td>
</tr>
<?php
}
?>
</table>
<?php
} else { echo "Data tidak tersedia."; }
?>

Selanjutnya kita bisa kembangkan coding tersebut dengan membuat aplikasi CRUD (Create, Read, Update, Delete) yang banyak digunakan di aplikasi web.
Selamat mencoba dan semoga sukses.

Membuat Database Web dengan MySQL

MySQL merupakan database yang umum digunakan dalam sebuah website atau aplikasi web. MySQL adalah RDMBS yang bersifat open source, free untuk Anda gunakan dan dapat juga berjalan di Windows maupun Linux.

Untuk menggunakan database MySQL Anda dapat mendownloadnya di website resminya www.mysql.com atau Anda dapat mendownload paket MySQL dalam XAMPP di www.apachefriends.org/en/xampp.html. Untuk belajar menggunakan databse MySQL saya rekomendasikan Anda mendownload XAMPP Portable Lite dalam bentuk 7zip yang lebih kecil sehingga nanti Anda dapat langsung menjalankannya tanpa perlu menginstall.

Setelah Anda donwload paket XAMPP Portable Lite, jalankan file xampp-control.exe untuk membuka XAMPP Control Panel lalu click tombol Start Apache dan MySQL untuk menjalankan service Web Server Apache dan Database Server MySQL.

XAMPP Control Panel

XAMPP Control Panel

Setelah itu buka Web browser Anda lalu ketik alamat: http://localhost/phpmyadmin/
maka akan terbuka PHPMyAdmin,  yakni tools yang sudah dipaket dalam XAMPP dan biasa digunakan untuk mengakses database MySQL.

Dengan PHPMyAdmin kita bisa membuat/create, melihat/read, mengubah/update, dan menghapus/delete, CRUD, database MySQL dengan mudah.

Nah… kita akan coba membuat sebuah database bernama “login_student” dengan struktur data sebagai berikut:

Struktur Data Tabel Login

Struktur Data Tabel Login

Berikut langkah-langkah untuk membuat database “login_student” di MySQL:

1. Pada halaman home PHPMyAdmin, click tab Databases lalu masukan nama database login_student lalu click tombol Create maka akan terbentuk database login_student.

Create DB MySQL

Create DB MySQL

2. Buka database login_student dengan meng-click daftar database di sebelah kiri lalu buatlah tabel “tabel_login_student” dengan jumlah kolom 11 seperti pada struktur data di atas.

Create Tabel Login Student

Create Tabel Login Student

3. Isilah nama kolom dan tipe datanya. Jika null di centang artinya kolom ini boleh kosong/tidak ada data, jika tidak dicentang atau not null artinya kolom ini harus ada data, jika tidak maka akan error pada saat insert record. Kolom id diberikan centang pada A_I (auto increament) artinya kolom id akan secara otomatis berisi angka berurutan pada saat insert record, tanpa perlu insert data id. Kolom id akan menjadi primary key dimana datanya unik atau tidak ada id yang sama.

Update Table MySQL

Update Table MySQL

Itulah cara singkat membuat database web dengan MySQL. Pemakaian database MySQL dalam web akan dibahas pada tuliasan berikutnya.

Selamat mencoba, semoga sukses.