เนื้อหานี้จะเป็นแนวทางการใช้งานระบบยืนยันตัวตน 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
https://www.ninenik.com/content.php?arti_id=978 via @ninenik
เกี่ยวกับ 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;
หวังว่าเนื้อหาต่อไปนี้จะมีประโยชน์ และเป็นแนวทางในการนำไปประยุกต์ใช้งานต่อไป