สร้างระบบลงชื่อเข้าใช้งาน (Login System) ความปลอดภัย 2 ชั้น ด้วย Google Authenticator และ PHP

สร้างระบบลงชื่อเข้าใช้งาน (Login System) ความปลอดภัย 2 ชั้น ด้วย Google Authenticator และ PHP

จากบทความ Google Authenticator คืออะไร? ผมได้อธิบายเกี่ยวกับ Feature หรือ แอพพลิเคชั่น (Application) ที่ทาง Google ได้พัฒนาขึ้นมาใหม่ ซึ่งเปิดตัวให้ใช้งานไปเมื่อไม่นานมานี้ เพื่อตรวจสอบความปลอดภัยในการเข้าถึงบัญชี และเข้าใช้งานระบบบริการต่างๆของ Google เพื่อยกระดับความปลอดภัยให้กับผู้ใช้งาน ด้วยแอพพลิเคชั่น Google Authenticator ที่ให้ดาวน์โหลดมาใช้งานกันได้ฟรีในสมาร์ทโฟน และแท็บเล็ต ที่ใช้ระบบปฏิบัติการ ทั้ง Android และ iOS ผ่านทาง Google Play และ App Store 

และในเมื่อทาง Google ได้พัฒนาแอพพลิเคชั่นที่เจ๋งๆแบบนี้ขึ้นมาให้เราใช้งานทั้งที เราก็น่าจะสามารถนำไปพัฒนา และประยุกต์ใช้งานกับระบบความปลอดภัยอื่นๆได้ วันนี้ผมเลยมาเขียนบทความแนะนำ การสร้างระบบลงชื่อเข้าใช้งาน (Login System) ความปลอดภัย 2 ชั้น ด้วย Google Authenticator และ PHP กันครับ

*** ก่อนอื่นอย่าลืมไปดาวน์โหลด แอพพลิเคชั่น Google Authenticator มาติดตั้งในสมาร์ทโฟนของเรา กันก่อนนะครับ

  

เมื่อทำการดาวน์โหลดแอพพลิเคชั่น Google Authenticator และติดตั้งลงในสมาร์ทโฟนของเรา และเปิดการใช้งานเรียบร้อยแล้ว ต่อไปเราจะประยุกต์ และทดสอบสร้างระบบลงชื่อเข้าใช้งาน (Login System) ความปลอดภัย 2 ชั้น ด้วย Google Authenticator และ PHP

ก่อนอื่นทำการดาวน์โหลด Google Authentication Library จาก Github ที่พัฒนาโดย PHPGangsta เพื่อนำมาใช้งานก่อนที่ https://github.com/PHPGangsta/GoogleAuthenticator

จากนั้นทำการสร้างฐานข้อมูล และตารางข้อมูลผู้ใช้งาน (Users Table) เพื่อเก็บข้อมูลผู้ใช้งานระบบ ดังนี้

Users Table

CREATE TABLE `users` (
`uid` int NOT NULL PRIMARY KEY AUTO_INCREMENT ,
`username` varchar(25) NOT NULL UNIQUE,
`password` varchar(200) NOT NULL ,
`email` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
`profile_pic` varchar(200) NOT NULL,
`google_auth_code` varchar(16) NOT NULL /* 16 digit code */
);

สำหรับโปรเจคนี้ผมจะใช้ PHP PDO Extension ในการเชื่อมต่อ และใช้งานฐานข้อมูล Mysql ดังนั้นอย่าลืม เปิดการใช้งาน PDO Extension ใน php.ini ด้วยนะครับ (วิธี Config ไฟล์ php.ini เพื่อเปิดใช้งาน PDO Extension)

จากนั้นสร้างไฟล์ config.php เพื่อเขียนคำสั่ง PHP ในการเชื่อมต่อฐานข้อมูล Database และ กำหนดค่าต่างๆ

config.php

<?php
session_start();
/* DATABASE CONFIGURATION */
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'username');
define('DB_PASSWORD', 'password');
define('DB_DATABASE', 'databasename');
define("BASE_URL", "http://localhost/PHPLoginHash/"); // Eg. http://yourwebsite.com

function getDB() 
{
$dbhost=DB_SERVER;
$dbuser=DB_USERNAME;
$dbpass=DB_PASSWORD;
$dbname=DB_DATABASE;
try {
$dbConnection = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser$dbpass); 
$dbConnection->exec("set names utf8");
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbConnection;
}
catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}

}
?>

หลังจากนั้นเขียนโปรแกรม PHP สร้างไฟล์ userClass.php เพื่อสร้าง Class และสร้างฟังก์ชั่น (Function) กำหนดการทำงานของระบบ และรับค่าต่างๆ จากฟอร์ม ในระบบที่เราสร้างขึ้น

userClass.php

<?php
class userClass
{
/* User Login */
public function userLogin($usernameEmail,$password)
{
try{
$db = getDB();
$hash_password= hash('sha256', $password); //Password encryption 
$stmt = $db->prepare("SELECT uid FROM users WHERE (username=:usernameEmail or email=:usernameEmail) AND password=:hash_password"); 
$stmt->bindParam("usernameEmail", $usernameEmail,PDO::PARAM_STR) ;
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->execute();
$count=$stmt->rowCount();
$data=$stmt->fetch(PDO::FETCH_OBJ);
$db = null;
if($count)
{
$_SESSION['uid']=$data->uid; // Storing user session value
$_SESSION['google_auth_code']=$google_auth_code; //Stroing Google authentication code
return true;
}
else
{
return false;

}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}

}

/* User Registration */
public function userRegistration($username,$password,$email,$name,$secret)
{
try{
$db = getDB();
$st = $db->prepare("SELECT uid FROM users WHERE username=:username OR email=:email");
$st->bindParam("username", $username,PDO::PARAM_STR);
$st->bindParam("email", $email,PDO::PARAM_STR);
$st->execute();
$count=$st->rowCount();
if($count<1)
{
$stmt = $db->prepare("INSERT INTO users(username,password,email,name,google_auth_code) VALUES (:username,:hash_password,:email,:name,:google_auth_code)");
$stmt->bindParam("username", $username,PDO::PARAM_STR) ;
$hash_password= hash('sha256', $password); //Password encryption
$stmt->bindParam("hash_password", $hash_password,PDO::PARAM_STR) ;
$stmt->bindParam("email", $email,PDO::PARAM_STR) ;
$stmt->bindParam("name", $name,PDO::PARAM_STR) ;
$stmt->bindParam("google_auth_code", $secret,PDO::PARAM_STR) ;
$stmt->execute();
$uid=$db->lastInsertId(); // Last inserted row id
$db = null;
$_SESSION['uid']=$uid;
return true;
}
else
{
$db = null;
return false;
}


catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}'; 
}
}

/* User Details */
public function userDetails($uid)
{
try{
$db = getDB();
$stmt = $db->prepare("SELECT email,username,name,google_auth_code FROM users WHERE uid=:uid");
$stmt->bindParam("uid", $uid,PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_OBJ); //User data
return $data;
}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
}
?>

ถัดไปเขียนคำสั่งสร้างฟอร์ม (Form) การสมัครสมาชิก (Signup Form) และฟอร์มการลงชื่อเข้าใช้งานระบบ (Login Form) และบันทึกเป็นไฟล์ index.php ดังนี้

index.php

<?php
include("config.php");
if(!empty($_SESSION['uid']))
{
header("Location: device_confirmations.php");
}
include('class/userClass.php');
$userClass = new userClass();

require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$secret = $ga->createSecret(); //This function will create unique 16 digit secret key

$errorMsgReg='';
$errorMsgLogin='';
/* Login Form */
if (!empty($_POST['loginSubmit'])) 
{
$usernameEmail=$_POST['usernameEmail'];
$password=$_POST['password'];
if(strlen(trim($usernameEmail))>1 && strlen(trim($password))>1 )
{
$uid=$userClass->userLogin($usernameEmail,$password);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php 
}
else
{
$errorMsgLogin="Please check login details.";
}
}
}

/* Signup Form */
if (!empty($_POST['signupSubmit'])) 
{
$username=$_POST['usernameReg'];
$email=$_POST['emailReg'];
$password=$_POST['passwordReg'];
$name=$_POST['nameReg'];
/* Regular expression check */
$username_check = preg_match('~^[A-Za-z0-9_]{3,20}$~i', $username);
$email_check = preg_match('~^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$~i', $email);
$password_check = preg_match('~^[A-Za-z0-9!@#$%^&*()_]{6,20}$~i', $password);

if($username_check && $email_check && $password_check && strlen(trim($name))>0) 
{
$uid=$userClass->userRegistration($username,$password,$email,$name);
if($uid)
{
$url=BASE_URL.'home.php';
header("Location: $url"); // Page redirecting to home.php 
}
else
{
$errorMsgReg="Username or Email already exists.";
}
}
}
?>
<!-- HTML Code -->
<!-- Login Form HTML Code -->


<div id="login">
<h3>Login</h3>
<form method="post" action="" name="login">
<label>Username or Email</label>
<input type="text" name="usernameEmail" autocomplete="off" />
<label>Password</label>
<input type="password" name="password" autocomplete="off"/>
<div class="errorMsg"><?php echo $errorMsgLogin; ?></div>
<input type="submit" class="button" name="loginSubmit" value="Login">
</form>
</div>


<!-- Signup Form HTML Code -->

<div id="signup">
<h3>Registration</h3>
<form method="post" action="" name="signup">
<label>Name</label>
<input type="text" name="nameReg" autocomplete="off" />
<label>Email</label>
<input type="text" name="emailReg" autocomplete="off" />
<label>Username</label>
<input type="text" name="usernameReg" autocomplete="off" />
<label>Password</label>
<input type="password" name="passwordReg" autocomplete="off"/>
<div class="errorMsg"><?php echo $errorMsgReg; ?></div>
<input type="submit" class="button" name="signupSubmit" value="Signup">
</form>
</div>

ถัดไปเขียนคำสั่ง CSS เพื่อกำหนดรูปแบบของฟอร์ม ให้ดูสวยงาม ดังนี้

Style CSS Code

#login,#signup{
width: 300px; border: 1px solid #d6d7da; 
padding: 0px 15px 15px 15px; 
border-radius: 5px;font-family: arial; 
line-height: 16px;color: #333333; font-size: 14px; 
background: #ffffff;rgba(200,200,200,0.7) 0 4px 10px -1px
}
#login{float:left;}
#signup{float:right;}
h3{color:#365D98}
form label{font-weight: bold;}
form label, form input{display: block;margin-bottom: 5px;width: 90%}
form input
border: solid 1px #666666;padding: 10px;
border: solid 1px #BDC7D8; margin-bottom: 20px
}
.button {
background-color: #5fcf80 ;
border-color: #3ac162;
font-weight: bold;
padding: 12px 15px;
max-width: 100px;
color: #ffffff;
}
.errorMsg{color: #cc0000;margin-bottom: 10px}

จากนั้นเขียน PHP เพื่อสร้างไฟล์ device_confirmation.php เพื่อรับค่า และตรวจสอบความถูกต้องของ รหัสยืนยันที่ถูกสร้างขึ้นมาจาก แอพพลิเคชั่น Google Authenticator ในสมาร์ทโฟนของเรา และส่งค่าเข้าไปในฟอร์ม การสมัครสมาชิก (Signup Form) และฟอร์มการลงชื่อเข้าใช้งานระบบ (Login Form) ดังนี้

device_confirmation.php

<?php
include('config.php');
if(empty($_SESSION['uid']))
{
header("Location: index.php");
}
include('class/userClass.php');
$userClass = new userClass();
$userDetails=$userClass->userDetails($_SESSION['uid']);
$secret=$userDetails->google_auth_code;
$email=$userDetails->email;

require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$qrCodeUrl = $ga->getQRCodeGoogleUrl($email, $secret,'Your Application Name');
?>
<!-- HTML Code -->
Enter the verification code generated by Google Authenticator app on your phone.
<div id="img">
<img src='<?php echo $qrCodeUrl; ?>' />
</div>

<form method="post" action="home.php">
<label>Enter Google Authenticator Code</label>
<input type="text" name="code" />
<input type="submit" class="button"/>
</form>

จากนั้นสร้างไฟล์ home.php เพื่อแสดงหน้าจอต้อนรับผู้ใช้งาน เมื่อทำการสมัครสมาชิก หรือลงชื่อเข้าสู่ระบบ

home.php

<?php
include('config.php');
include('class/userClass.php');
$userClass = new userClass();
$userDetails=$userClass->userDetails($_SESSION['uid']);

if($_POST['code'])
{
$code=$_POST['code'];
$secret=$userDetails->google_auth_code;
require_once 'googleLib/GoogleAuthenticator.php';
$ga = new GoogleAuthenticator();
$checkResult = $ga->verifyCode($secret, $code, 2);    // 2 = 2*30sec clock tolerance

if ($checkResult)
{
$_SESSION['googleCode']=$code;
}
else
{
echo 'FAILED';
}
}

include('session.php');
$userDetails=$userClass->userDetails($session_uid);
?>
<!-- HTML Code -->
<h1>Welcome <?php echo $userDetails->name; ?></h1>
<h2> Email <?php echo $userDetails->email; ?></h2>
<a href="<?php echo BASE_URL; ?>logout.php">Logout</a>

สร้างไฟล์ session.php เพื่อตรวจสอบ session การ login ของผู้ใช้งาน

session.php

<?php
if(!empty($_SESSION['uid']) && !empty($_SESSION['googleCode']))
{
$session_uid=$_SESSION['uid'];
$session_googleCode=$_SESSION['googleCode'];
}
if(empty($session_uid) && empty($session_googleCode))
{
$url=BASE_URL.'index.php';
header("Location: $url");
}
?>

และสุดท้ายสร้างไฟล์ logout.php (ออกจากระบบ) เพื่อล้างค่าข้อมูลต่างๆ รวมถึง session ของผู้ใช้งาน

logout.php

<?php
include('config.php');
$session_uid='';
$session_googleCode='';
$_SESSION['uid']='';
$_SESSION['googleCode']='';
if(empty($session_uid) && empty($_SESSION['uid']))
{
$url=BASE_URL.'index.php';
header("Location: $url");
}
?>

จากเนื้อหา และคำอธิบายในข้างต้น รวมถึง Souce Code หากว่าทดลองทำตาม และทดสอบสร้าง ระบบลงชื่อเข้าใช้งาน (Login System) ความปลอดภัย 2 ชั้น ด้วย Google Authenticator และ PHP ตามวิธีที่ได้อธิบายไป ก็จะได้ผลลัพธ์ และแนวทางที่จะสามารถนำไปประยุกต์ใช้งานกับระบบงานต่างๆ ที่ต้องการเพิ่มความปลอดภัยได้อีกทางเลือกหนึ่ง หวังว่าจะมีประโยชน์สำหรับผู้ที่สนใจหลายๆคนนะครับ^^


Siamhttp สยามเอชทีทีพี, บริการรับทำเว็บไซต์, บริการออกแบบเว็บไซต์, บริการออกแบบเว็บไซต์รองรับสมาร์ทโฟน, Responsive Website Design, SEO, พัฒนาโปรแกรมบนเว็บ ราคาเบาๆ

แชร์บทความ

Facebook Twitter Google Digg Reddit LinkedIn StumbleUpon Email
กำลังโหลด ...