ใช้งานระบบยืนยัน 2 ชั้น 2FA ด้วย Google Authenticator ร่วมกับ PHP

บทความ เมื่อไม่กี่สัปดาห์ โดย Ninenik Narkdee
google authenticator 2fa microsoft authenticator google2fa endroidqrcode totp

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ google authenticator 2fa microsoft authenticator google2fa endroidqrcode totp

ดูแล้ว 656 ครั้ง


เนื้อหานี้จะเป็นแนวทางการใช้งานระบบยืนยันตัวตน 2 ชั้น 
(Two-Factor Authentication, 2FA) เพื่อเพิ่มระดับความปลอดภัยในการเข้า
ถึงข้อมูลสมาชิก ในที่นี้จะมีการใช้ package 2 ตัวมาร่วม คือ Google2FA สำหรับสร้าง
TOTOP (Time-based One-time Password) กับ EndroidQrCode สำหรับ
สร้างรูป qrcode ไว้สำหรับแอปพลิเคชันยืนยันตัวตนอย่าง Google Authenticator 
หรือ Microsoft Authenticator เพื่อสแกนเปิดใช้งาน
 
สำหรับ Google2FA และ EndroidQrCode จะใช้เป็นเวอร์ชั่นดังนี้
 

ติดตั้ง Google2FA และ EndroidQrCode ก่อนใช้งาน 

 
composer require pragmarx/google2fa:8.0
composer require endroid/qr-code:3.8.1
 
โดย EndroidQrCode เวอร์ชั่นดังกล่าว สามารถดูวิธีการใช้งานแบบกระชับ
ได้ที่บทความด้านล่างนี้  หากใช้เวอร์ชั่นอื่น อาจจะต้องดูคู่มือหรือการกำหนดค่าใหม่ 
ตามเวอร์ชั่นนั้นๆ
 
 
สร้าง qrcode ด้วย php endroid qrcode อัพเดทปี 2020 http://niik.in/978 
 

เกี่ยวกับ Google2FA

 
Google2FA เป็น โมดูล PHP ที่รองรับการใช้งานร่วมกับ Google Two-Factor Authentication 
หรือระบบยืนยันตัวตนสองชั้นของ Google สามารถใช้ได้ทั้ง (HOTP) และ  (TOTP) อัลกอริทึม (Algorithm)
เนื่องจากระบบทั้งสองมีเรื่องของการใช้เวลามาเกี่ยวข้องดังนั้น ต้องให้มั่นใจว่าอุปกรณ์ที่เราใช้ยืนยันตัวตน (มือถือที่
ติดตั้งแอปพลิเคชันยืนยันตัวตน) กับเวลาของ server ต้องตรงกัน เพราะว่าจะมีการใช้งานรหัสข้อมูลค่าเดียวกันใน
เวลาที่กำหนดเอาไว้ 
 

TOTP ในระบบ 2FA คืออะไร

 
TOTP ย่อมาจาก "Time-Based One-Time Password" หรือ "การสร้างรหัสผ่านใช้ครั้งเดียวโดยใช้เวลา" 
ซึ่งเป็นหนึ่งในวิธีการที่ใช้ในการสร้างรหัสผ่านสำหรับการยืนยันตัวตนสองชั้น (Two-Factor Authentication, 2FA) 
หรือการยืนยันตัวตนหลายชั้น (Multi-Factor Authentication, MFA) โดยรหัสผ่านนี้มีอายุการใช้งานจำกัด
และเปลี่ยนไปตามเวลาปัจจุบัน โดยมักจะใช้เป็นหนึ่งในตัวเลือกในการยืนยันตัวตนเมื่อใช้แอปพลิเคชันยืนยันตัวตน 
อย่างเช่น Google Authenticator หรือ Microsoft Authenticator
 
โดยวิธีการทำงานของ TOTP จะใช้การสร้างรหัสผ่านสำหรับยืนยันตัวตนจากข้อมูลหลายๆ อย่างที่เปลี่ยนไป
ตามเวลาปัจจุบัน (timestamp) โดยสมมติว่าเรามีข้อมูลรหัสลับ (secret key) และข้อมูลเวลาปัจจุบัน
 (timestamp) ซึ่งสามารถปรับแต่งได้ทุกๆ 30 วินาที จากนั้นจะนำข้อมูลรหัสลับและข้อมูลเวลาปัจจุบัน
มาผ่านอัลกอริทึมแฮชเชียร์ เช่น HMAC-SHA1 เพื่อสร้างรหัสผ่านชุดใหม่ จากนั้นนำผลลัพธ์ที่ได้
มาตัดส่วนบางส่วนออก และเอาผลลัพธ์นั้นมาแปลงเป็นรหัสผ่านที่มีความยาวและของอักขระที่กำหนดไว้
 
เมื่อผู้ใช้ต้องการยืนยันตัวตน ระบบจะถามหารหัสผ่านใหม่จากแอปพลิเคชันยืนยันตัวตน และใช้ข้อมูล
เวลาปัจจุบัน (timestamp) เพื่อสร้างรหัสผ่านใหม่ขึ้นมา โดยรหัสผ่านที่ถูกสร้างนี้จะมีอายุการใช้งาน
เพียงแค่ไม่กี่วินาที จึงทำให้มันเป็นรหัสผ่านใช้ครั้งเดียวที่ปลอดภัยและทันสมัย
 

HOTP ในระบบ 2FA คืออะไร

 
HOTP ย่อมาจาก "HMAC-based One-Time Password" หรือ "การสร้างรหัสผ่านใช้ครั้งเดียวโดยใช้ HMAC" 
ซึ่งเป็นวิธีการสร้างรหัสผ่านสำหรับการยืนยันตัวตนสองชั้น (Two-Factor Authentication, 2FA) 
หรือการยืนยันตัวตนหลายชั้น (Multi-Factor Authentication, MFA) ที่ใช้การถอดรหัสด้วย 
HMAC (Hash-based Message Authentication Code) เพื่อสร้างรหัสผ่านที่มีอายุการใช้งานจำกัด
และเปลี่ยนไปตามข้อมูลที่มีอยู่
 
วิธีการทำงานของ HOTP จะใช้การสร้างรหัสผ่านโดยใช้ข้อมูลรหัสลับ (secret key) และข้อมูลการตรวจสอบ
(counter) ที่เปลี่ยนไปเมื่อมีการใช้งาน โดยรหัสลับและข้อมูลการตรวจสอบนี้จะถูกส่งผ่านฟังก์ชันแฮช 
(hash function) เช่น HMAC-SHA1 เพื่อสร้างรหัสผ่านที่มีความยาวและของอักขระที่กำหนดไว้
 
เมื่อผู้ใช้ต้องการยืนยันตัวตน ระบบจะถามหารหัสผ่านใหม่จากแอปพลิเคชันยืนยันตัวตน และใช้ข้อมูลการ
ตรวจสอบ (counter) เพื่อสร้างรหัสผ่านใหม่ขึ้นมา โดยรหัสผ่านที่ถูกสร้างนี้จะมีอายุการใช้งานเพียงแค่ครั้งเดียว 
และหลังจากนั้นระบบจะเพิ่มค่า counter หรือข้อมูลการตรวจสอบเพื่อใช้สำหรับการยืนยันตัวตนครั้งถัดไป
 
สรุปคือ ทั้ง TOTP และ HOTP นั้นเป็นวิธีการสร้างรหัสผ่านใช้ครั้งเดียวที่มีความปลอดภัยและเปลี่ยนไป
ตามข้อมูลการตรวจสอบที่เปลี่ยนไป ซึ่งเป็นหนึ่งในวิธีการที่นิยมใช้ในการทำงานของระบบยืนยันตัวตนสองชั้น
(2FA) หรือหลายชั้น (MFA) เพื่อเพิ่มความปลอดภัยในการเข้าถึงข้อมูลและบริการออนไลน์
**ในที่นี้เราจะใช้เป็นรูปแบบ TOTP 
 
 

แนวทางการประยุกต์การใช้งาน ระบบยืนยัน 2 ชั้น 2FA กับระบบสมาชิก

 
เมื่อเรารู้จักเครื่องมือที่จะใช้งานแล้ว ก็มีดูแนวทางการทำงานและการประยุกต์ สมมติเรามีระบบสมาชิกเดิมอยู่แล้ว
ปกติการทำงานก็คือ ผู้ใช้ล็อกอินเข้าใช้งานด้วย ชื่อผู้ใช้ และ รหัสผ่าน ก็จะเข้าสู่ระบบสมาชิกได้ ดังนั้น การที่จะ
เปิดใช้งานระบบยืนยัน 2 ชั้น ผู้ใช้จะต้องเข้ามาในหน้าจัดการสมาชิก หรือเข้าสู่ระบบก่อน สิ่งที่เราต้องเพิ่มเข้าไป
ในระบบสมาชิก คือฟิลด์ที่สำหรับ เปิดใช้งานยืนยัน เพื่อแยกว่าใครจะใช้หรือไม่ใช้ระบบยืนยัน 2 ชั้น และอีกฟิลด์
คือรหัสสำหรับปิดการใช้งานระบบยืนยัน 2 ชั้น เราไม่สามารถเข้าถึงอุปกรณ์ยืนยันตัวตนได้ ต้องการปิดระบบก็จะ
ใช้รหัสพิเศษนี้เพื่อปิดการใช้งาน ให้เข้าสู่ระบบแบบปกติ สมมติเราใช้ชื่อฟิลด์ทั้งสองเป็นดังนี้
 
member_2fa_active เก็บค่า 0 กับ 1 (ปิดใช้งาน กับ เปิดใช้งาน)
member_2fa_revoke_key เก็บ ข้อความรหัสพิเศษ (สร้างให้ตอนแรกที่เปิดใช้งาน แล้วให้บันทึกเก็บไว้)
 
โดยค่าแรก เมื่อเราเข้าสู่ระบบสมาชิกได้แล้ว ก็สามารถปิดเปิดได้ตามต้องการ 
ส่วนค่าที่สอง เราจะใช้สำหรับเป็นรหัสยืนยัน กรณีที่ยังไม่ได้ล็อกอิน หรือล็อกอิน 2 ชั้นไม่ได้ ต้องการปิด ก็จะใช้
ค่าที่บันทึกไว้นี้เป็นรหัสเพื่อยืนยันว่าเราเป็นผู้ใช้ที่ต้องการปิดค่า member_2fa_active ให้เป็น 0 เพื่อให้
สามารถล็อกอินผ่านระบบสมาชิกปกติ
 

ลำดับภาพตัวอย่าง ขั้นตอนการทำงาน เมื่ออยู่ในหน้าสมาชิก

 
1. เริ่มต้น เปิดใช้งานครั้งแรก ในหน้าสมาชิก เมื่อเข้าสู่ระบบอยู่แล้ว มีหน้าจัดการ การเปิดใช้งาน 2FA
โดยเมื่อผู้ใช้เลือกเปิดใช้งาน เราก็จะทำการสร้าง qrcode สำหรับใช้แอปพลิเคชันยืนยันตัวตนสแกน
แต่ถ้าเปิดใช้งานอยู่แล้ว ต้องการปิด เราก็สามารถทำคำสั่งอัปเดทฐานข้อมูลใน  member_2fa_active
ให้มีค่าเป็น 0
 


 
 
2. กรณีเป็นการเปิดใช้งาน ก็ให้ไปยังหน้าสร้าง qrcode สำหรับแอปพลิเคชันยืนยันตัวตน 
 


 
 
เพื่อเปิดใช้งานผู้ใช้จะต้องใช้แอปพลิเคชันยืนยันตัวตนสแกน จากนั้นนำค่า ตัวเลข 6 หลักหรือ
otp มากรอก เพื่อยืนยันการเปิดใช้งาน 
 
3. ในขั้นตอนนี้ ถ้ากรอกข้อมูลถูกต้อง ก็จะแจ้งว่าทำการ เปิดใช้งาน ระบบยืนยัน 2 ชั้น สำเร็จและ
ทำการอัปเดทฐานข้อมูลที่กล่าวไปแล้วข้างต้น รวมถึงแสดงรหัสสำหรับใช้ปลดล็อค เพื่อปิดระบบ
ยืนยัน 2 ชั้นกรณี ไม่สามารถใช้งานอุปกรณ์ยืนยันได้
 

 
 
 

ลำดับภาพตัวอย่าง ขั้นตอนการทำงาน เมื่อจะล็อกอินเข้าใช้งานแบบรองรับระบบยืนยัน 2 ชั้น

 
1. หน้าล็อกอินปกติ ผู้ใช้กรอก ชื้อผู้ใช้ และรหัสผ่านปกติ
 

 
 
ในขั้นตอนการล็อกอินปกติ เมื่อผู้ใช้กรอกข้อมูลถูกต้อง เราก็จะทำการสร้าง session ข้อมูล เพื่อเป็นเงื่อนไข
การเข้าใช้งาน แต่กรณีให้รองรับระบบยืนยัน 2 ชั้น เราจะต้องเพิ่มเงื่อนไขการตรวจสอบเข้าไปอีกชั้นก่อน
 
ตัวอย่าง
if($login_pass==true){
  if($have_2fa==1){ // ตรวจสอบก่อนว่า มีการเปิดใช้งานล็อกอิน 2 ชั้นหรือไม่
            // สร้างตัวแปร session เฉพาะที่จำเป็นชั่วคราว เพื่อใช้งานกับการยืนยัน 2 ชั้น
            // ในที่นี้คือเราจะต้องดึงข้อมูลสมาชิกที่บันทึกไว้ 2 ค่ามาใช้งาน คือ userid กับ ค่า
       // google2fa_secret ที่สร้างและบันทึกในฐานข้อมูลครั้งแรกที่เปิดใช้งาน
            // ให้ทำการ redirect ไปหน้าสำหรับกรอก otp
   }else{  // กรณีไม่ได้เปิดใช้งาน 2FA ก็ให้ทำงานปกติ
            // สร้าง session ข้อมูลสมาชิก สำหรับใช้งาน
   }
}
 
2. ในหน้าสำหรับกรอก otp ผู้ใช้จะต้องใช้รหัส otp จากแอปพลิเคชันยืนยันตัวตนเพื่อทำการ
ยืนยันการเข้าใช้งาน หน้านี้จะเป็นแค่หน้าฟอร์มทำธรรมดาสำหรับส่งข้อมูลเท่านั้น โดยจะทำการส่ง
ค่าไปยังไฟล์ verify.php หรือไฟล์ที่เรากำหนด เพื่อทำการตรวจสอบ ข้อมูล คล้ายๆกับขึ้นตอนการ
เปิดใช้งานครั้งแรก แต่ครั้งนี้ จะใช้ google2fa_secret จากฐานข้อมูลที่เราได้บันทึกไว้มาใช้งาน
 


 
 
หากทำการกรอกข้อมูลถูกต้อง ก็เข้าสู่ระบบสมาชิกและสร้าง session ข้อมูลทั้งหมดที่จำเป็น
 
3. ในหน้าขั้นตอนที่ 2 เราอาจจะมีลิ้งค์สำหรับกรณี ผู้ใช้ไม่สามารถใช้อุปกรณ์ยืนยันตัวตนได้ และต้อง
การปิดการใช้งาน และผู้ใช้ได้บันทึกรหัส google2fa_secret ไว้แล้ว ก็สามารถทำการลิ้งค์ไปยังหน้า
ปิดการใช้งานระบบยืนยัน 2 ชั้นได้
 


 
 
เมื่อกรอกรหัสถูกต้อง ก็ทำการแจ้งว่าปิดระบบเรียบร้อยแล้ว และให้ผู้ใช้ทำการเข้าสู่ระบบใหม่อีกครั้ง
 
ทั้งหมดก็เป็นขั้นตอนการทำงานของรูปแบบการใช้งาน ระบบยืนยัน 2 ชั้น 
 

ตัวอย่างโค้ดการประยุกต์ระบบยืนยัน 2 ชั้น 2FA

 
โค้ดตัวอย่าง แยกทีละไฟล์ เพื่อให้เห็นภาพ ไม่ได้ประยุกต์หรือเพิ่มโค้ดทั้งหมด 
 

ไฟล์ member.php

 
<?php
session_start();
// สำหรับทดสอบ กรณียังไม่มีข้อมูล
if(!isset($_SESSION['userinfo'])){
    $_SESSION['userinfo'] = [
        'userid'=>'userid3456789',
    ];
}
// จำลองการปิดการใช้งานระบบ 2 ชั้น สามารถประยุกต์แบบปิดชั่วคราว และปิดถาวรได้
if(isset($_GET['revoke'])){
    unset($_SESSION['userinfo']['2fa_active']);
}
$_2fa_active = (isset($_SESSION['userinfo']['2fa_active']) 
&& $_SESSION['userinfo']['2fa_active']==1)?" checked":"";
?>

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Member Settings</title>
    <!-- Bootstrap CSS -->
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .login-container {
            max-width: 400px;
            margin: 0 auto;
            margin-top: 100px;
        }

        .form-container {
            margin: 0 auto;
            margin-top: 100px;
        }
    </style>
</head>

<body>
 

    <div class="container login-container">
        <h2 class="text-center mb-4">Settings</h2>
        <div class="form-group">
            <label for="2faToggle">Two-Factor Authentication</label>
            <div class="custom-control custom-switch">
                <input type="checkbox" class="custom-control-input"
                 id="2faToggle" <?=$_2fa_active?> onchange="toggle2FA(this.checked)">
                <label class="custom-control-label" for="2faToggle">Enable 2FA</label>
            </div>
        </div>
    </div>
    <div class="container login-container">
        <pre>
            <?php print_r($_SESSION['userinfo']); ?>
        </pre> 
        <a href="login.php"> Login Page.</a>
    </div>

    <!-- JavaScript -->
    <script>
        function toggle2FA(enabled) {
            if (enabled) {
                window.location = 'activate_2fa.php';
                // Send request to enable 2FA
                console.log('2FA enabled');
            } else {
                window.location = 'member.php?revoke=1';                
                // Send request to disable 2FA
                console.log('2FA disabled');
            }
        }
    </script>




</body>

</html>

 
 

ไฟล์ activate_2fa.php

 
<?php
use PragmaRX\Google2FA\Google2FA;
use Endroid\QrCode\QrCode;
// Start Server Session
session_start();

require '../vendor/autoload.php';

$google2fa = new Google2FA();

$_SESSION['userinfo'] = [
    'userid'=>'userid3456789',
    'google2fa_secret'=>''  // กรณีเปิดใช้งาน
];
$_SESSION['userinfo']['google2fa_secret'] = $google2fa->generateSecretKey();


// เรียกใช้ session ผ่านตัวแปร 
$user = $_SESSION['userinfo'];
// $user['google2fa_secret'] // ค่านี้จะต้องถูกบันทึกในฐานข้อมูลเพื่อใช้งาน ถ้าเปิดใช้

// กำหนดชื่อแอป ที่จะใช้งาน
$app_name = 'Ninenik.com';

// ข้อมูลที่จะใช้สร้างคิวอาร์โค้ด
$qrCodeUrl = $google2fa->getQRCodeUrl(
    $app_name,
    $user['userid'], // ใช้ค่าที่เป็นเฉพาะ อาจจะเป็นเบอร์โทรหรืออีเมลก็ได้ ต้องไม่ซ้ำกัน
    $user['google2fa_secret']
);

// กำหนดข้อคาม ค่า หรือข้อมูลที่ต้องการแสดงใน qrcode
$qrCode = new QrCode($qrCodeUrl);
$qrCode->setSize(200); 
// กำหนดขนาดตามต้องการ หน่วย pixel ถ้าไม่กำหนดค่าเริ่มต้นเท่ากับ 300

// สร้างรูปภาพคิวอาร์โค้ดสำหรับแสดงเพื่อสแกน เปิดใช้งาน
$encoded_qr_data = $qrCode->writeDataUri();

// ค่า otp ที่ถูกสร้างทันทีใช้เรียกใช้งาน
$current_otp = $google2fa->getCurrentOtp($user['google2fa_secret']);
?>


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Two-Factor Authentication</title>
    <!-- Bootstrap CSS -->
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .login-container {
            max-width: 400px;
            margin: 0 auto;
            margin-top: 100px;
        }

        .form-container {
            margin: 0 auto;
            margin-top: 100px;
        }
    </style>
</head>

<body>

    <div class="container form-container text-center">
        หน้านี้จะทำการสร้างคิวอาร์โค้ด และสแกนแค่ครั้งแรกเท่านั้น ถ้าจะสแกนใหม่<br>
        ต้องทำการลบข้อมูลเดิมในแอปออกก่อน
        <h1>Two-Factor Authentication</h1>
        <h2>QR Code</h2>
        <p><img src="<?= $encoded_qr_data; ?>" alt="QR Code"></p> 
        
        Enter TOTP: <input type="number" name="otp" id="otp" required />
        <input type="button" value="Verify" onclick="verify_otp();" />
        <br>
        <p>
        <a href="member.php"> Member.</a>
        </p>
    </div>

    <script>
        let input_otp = document.getElementById('otp');

        const verify_otp = async () => {
            let otp = document.getElementById('otp').value;
            const payload_data = {
                active: 1,
                otp: otp
            };
            const queryParams = new URLSearchParams(payload_data).toString();
            fetch('verify.php?' + queryParams)
                .then((response) => response.json())
                .then((data) => {
                    console.log(data)
                    if (data.result == true) {
                        alert("Valid OTP");
                        window.location='success_2fa.php';
                    } else {
                        alert("Invalid OTP !!!");
                        input_otp.value = '';
                    }
                });
        }
    </script>




</body>

</html>

 
 

ไฟล์ success_2fa.php


<?php
session_start();
$user = $_SESSION['userinfo'];
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Two-Factor Authentication Enabled</title>
    <!-- Bootstrap CSS -->
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .login-container {
            max-width: 400px;
            margin: 0 auto;
            margin-top: 100px;
        }

        .form-container {
            margin: 0 auto;
            margin-top: 100px;
        }
    </style>
</head>

<body>
  

    <div class="container login-container">
        <h2 class="text-center mb-4">Two-Factor Authentication Enabled</h2>
        <div class="alert alert-success" role="alert">
        Two-Factor Authentication has been successfully enabled.
        </div>
        <p>Your reset code is: <?=$user['google2fa_secret']?></p>
        <p id="resetCode"></p>
        <div class="alert alert-info" role="alert">
        <strong>Important:</strong> Please copy or save this reset code in a safe place.
         You will need it to recover your account if you lose access to your 
         authenticator app.       
        </div>    
        <br>
            <p>
            <a href="member.php"> Member</a>
            </p>              
    </div>



</body>

</html>
 
 

ไฟล์ login.php

 
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login Form</title>
    <!-- Bootstrap CSS -->
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .login-container {
            max-width: 400px;
            margin: 0 auto;
            margin-top: 100px;
        }

        .form-container {
            margin: 0 auto;
            margin-top: 100px;
        }
    </style>
</head>

<body>
    <div class="container login-container">
        <h2 class="text-center mb-4">Login</h2>
        <form action="2fa_verify.php" method="post">
            <div class="form-group">
                <label for="username">Username</label>
                <input type="text" class="form-control" id="username" name="username" value="userid3456789" required>
            </div>
            <div class="form-group">
                <label for="password">Password</label>
                <input type="password" class="form-control" id="password" name="password" value="test" required>
            </div>
            <button type="submit" class="btn btn-primary btn-block">Login</button>
        </form>
    </div>



</body>

</html>

 
 

ไฟล์ 2fa_verify.php

 
<?php
session_start();
// ถ้ามาหน้านี้ ต้องมีข้อมูลสองค่านี้เสมอ เพื่อใช้สำหรับการตรวจสอบ
// ดึงจากฐานข้อมูลที่ได้บันทึกไว้
$_SESSION['userinfo'] = [
    'userid'=>'userid3456789',
    'google2fa_secret'=>'RUIAW5PTZZ5DVWDR' // สมมติค่าตัวอย่างที่บันทึกไว้แล้ว
];
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Two-Factor Authentication</title>
    <!-- Bootstrap CSS -->
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .login-container {
            max-width: 400px;
            margin: 0 auto;
            margin-top: 100px;
        }

        .form-container {
            margin: 0 auto;
            margin-top: 100px;
        }
    </style>
</head>

<body>



    <div class="container login-container">
        <h2 class="text-center mb-4">Two-Factor Authentication</h2>
        <form action="verify_totp.php" method="post" onsubmit="return false;">
            <div class="form-group">
                <label for="totp">Enter TOTP Token</label>
                <input type="number" class="form-control" id="otp" name="otp" required>
            </div>
            <button type="submit" class="btn btn-primary btn-block" onclick="verify_otp();">Verify</button>
            <br>
            <p>
            <a href="disabled_2fa.php"> if you lose access to your authenticator app.</a>
            </p>
        </form>
    </div>


    <script>
        let input_otp = document.getElementById('otp');

        const verify_otp = async () => {
            let otp = document.getElementById('otp').value;
            const payload_data = {
                login: 1,
                otp: otp
            };
            const queryParams = new URLSearchParams(payload_data).toString();
            fetch('verify.php?' + queryParams)
                .then((response) => response.json())
                .then((data) => {
                    console.log(data)
                    if (data.result == true) {
                        alert("Valid OTP");
                        window.location='member.php';
                    } else {
                        alert("Invalid OTP !!!");
                        input_otp.value = '';
                    }
                });
        }
    </script>





</body>

</html>

 
 

ไฟล์ disabled_2fa.php

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Disable Two-Factor Authentication</title>
    <!-- Bootstrap CSS -->
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .login-container {
            max-width: 400px;
            margin: 0 auto;
            margin-top: 100px;
        }

        .form-container {
            margin: 0 auto;
            margin-top: 100px;
        }
    </style>
</head>

<body>


    <div class="container login-container">
        <h2 class="text-center mb-4">Disable Two-Factor Authentication</h2>
        <form action="disable_2fa.php" method="post">
            <div class="form-group">
                <label for="resetCode">Reset Code</label>
                <input type="text" class="form-control" id="resetCode" name="resetCode" required>
                <small id="resetCodeHelp" class="form-text text-muted">Enter the reset code sent to your email or phone.</small>
            </div>
            <button type="submit" class="btn btn-danger btn-block">Disable 2FA</button>
            <br>
            <p>
            <a href="login.php"> Login Page.</a>
            </p>
        </form>
    </div>



</body>

</html>

 
 

ไฟล์ verify.php

 
<?php
use PragmaRX\Google2FA\Google2FA;
session_start();

require '../vendor/autoload.php';

$google2fa = new Google2FA();

// ใช้ข้อมูลผู้ใช้งานจาก session
$user = $_SESSION['userinfo'];

// รับค่า otp ที่กรอกเข้ามา
$otp = (isset($_GET['otp']))?$_GET['otp']:'';

// ตรวจสอบความถูกต้องของรหัส otp ถ้าถูกต้องส่งกลับค่าเป็น true / false
$valid = $google2fa->verifyKey($user['google2fa_secret'], $otp);

$response = [
    'input_otp' =>  $otp,
    'result'    =>  $valid
];
if(isset($_GET['active']) && $_GET['active']==1 && $valid==true){
    // ทำคำสั่งอัพเดทฟิลด์ข้อมูลในฐานข้อมูลของสมาชิก 
    // member_2fa_active  เท่ากับ 1 (เปิดใช้งาน)
    // member_2fa_revoke_key  ให้ใช้ค่าเป็น $user['google2fa_secret']  
    $_SESSION['userinfo']['2fa_active']=1;
}
if(isset($_GET['login']) && $_GET['login']==1 && $valid==true){
    // สร้าง session ที่เกี่ยวกับระบบสมาชิก 
    $_SESSION['userinfo']['2fa_active']=1;
}
$response = json_encode($response);
echo $response;

 
 
 
หวังว่าเนื้อหาต่อไปนี้จะมีประโยชน์ และเป็นแนวทางในการนำไปประยุกต์ใช้งานต่อไป

 


กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ











URL สำหรับอ้างอิง





คำแนะนำ และการใช้งาน

สมาชิก กรุณา ล็อกอินเข้าระบบ เพื่อตั้งคำถามใหม่ หรือ ตอบคำถาม สมาชิกใหม่ สมัครสมาชิกได้ที่ สมัครสมาชิก


  • ถาม-ตอบ กรุณา ล็อกอินเข้าระบบ
  • เปลี่ยน


    ( หรือ เข้าใช้งานผ่าน Social Login )







เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ