ดูวิธีเพิ่มประสิทธิภาพแบบฟอร์ม OTP ทาง SMS และปรับปรุงประสบการณ์ของผู้ใช้
การขอให้ผู้ใช้ระบุ OTP (รหัสผ่านที่สามารถใช้งานได้เพียงครั้งเดียว) ที่ส่งผ่าน SMS เป็นวิธีทั่วไปในการยืนยันหมายเลขโทรศัพท์ของผู้ใช้ กรณีการใช้งาน OTP ทาง SMS มีดังนี้
- การตรวจสอบสิทธิ์แบบ 2 ปัจจัย นอกจากชื่อผู้ใช้และรหัสผ่านแล้ว OTP ทาง SMS ยังใช้เป็นสัญญาณที่ชัดเจนว่าบัญชีเป็นของบุคคลที่ได้รับ OTP ทาง SMS
- การยืนยันหมายเลขโทรศัพท์ บริการบางอย่างใช้หมายเลขโทรศัพท์เป็นตัวระบุหลักของผู้ใช้ ในบริการดังกล่าว ผู้ใช้จะป้อนหมายเลขโทรศัพท์และ OTP ที่ได้รับทาง SMS เพื่อพิสูจน์ตัวตนได้ บางครั้งก็ใช้ร่วมกับ PIN เพื่อใช้ตรวจสอบสิทธิ์แบบ 2 ปัจจัย
- การกู้คืนบัญชี เมื่อผู้ใช้สูญเสียสิทธิ์เข้าถึงบัญชี จะต้องมีวิธีกู้คืนบัญชี การส่งอีเมลไปยังอีเมลที่ลงทะเบียนไว้หรือส่ง OTP ทาง SMS ไปยังหมายเลขโทรศัพท์เป็นวิธีการกู้คืนบัญชีที่พบได้ทั่วไป
- การยืนยันการชำระเงิน ในระบบการชำระเงิน ธนาคารหรือผู้ออกบัตรเครดิตบางรายจะขอการตรวจสอบสิทธิ์เพิ่มเติมจากผู้ชำระเงินเพื่อเหตุผลด้านความปลอดภัย โดยปกติแล้วระบบจะใช้ OTP ทาง SMS เพื่อวัตถุประสงค์ดังกล่าว
โพสต์นี้จะอธิบายแนวทางปฏิบัติแนะนำในการสร้างแบบฟอร์ม OTP ทาง SMS สำหรับกรณีการใช้งานข้างต้น
เช็กลิสต์
ทำตามขั้นตอนต่อไปนี้เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีที่สุดด้วย OTP ทาง SMS
- ใช้องค์ประกอบ
<input>
กับสิ่งต่อไปนี้type="text"
inputmode="numeric"
autocomplete="one-time-code"
- ใช้
@BOUND_DOMAIN #OTP_CODE
เป็นบรรทัดสุดท้ายของข้อความ OTP ทาง SMS - ใช้ WebOTP API
ใช้องค์ประกอบ <input>
การใช้แบบฟอร์มที่มีองค์ประกอบ <input>
เป็นแนวทางปฏิบัติแนะนำที่สำคัญที่สุดที่คุณทำได้ เนื่องจากใช้งานได้กับเบราว์เซอร์ทุกรุ่น แม้ว่าคำแนะนำอื่นๆ จากโพสต์นี้จะไม่ทำงานในบางเบราว์เซอร์ แต่ผู้ใช้จะยังคงป้อนและส่ง OTP ด้วยตนเองได้
<form action="/verify-otp" method="POST">
<input type="text"
inputmode="numeric"
autocomplete="one-time-code"
pattern="\d{6}"
required>
</form>
ต่อไปนี้เป็นแนวคิดบางส่วนที่จะช่วยให้ช่องป้อนข้อมูลได้รับประโยชน์สูงสุดจากฟังก์ชันการทำงานของเบราว์เซอร์
type="text"
เนื่องจาก OTP มักจะเป็นตัวเลข 5 หรือ 6 หลัก การใช้ type="number"
สำหรับช่องป้อนข้อมูลจึงดูเป็นวิธีที่เข้าใจง่ายเนื่องจากจะเปลี่ยนแป้นพิมพ์ของอุปกรณ์เคลื่อนที่เป็นตัวเลขเท่านั้น ไม่แนะนําให้ทําเช่นนี้ เนื่องจากเบราว์เซอร์คาดหวังว่าช่องป้อนข้อมูลจะเป็นจํานวนนับได้ ไม่ใช่ลําดับของจํานวนหลายรายการ ซึ่งอาจทําให้ระบบทํางานอย่างไม่คาดคิด การใช้ type="number"
จะทําให้ปุ่มขึ้นและลงแสดงข้างช่องป้อนข้อมูล การกดปุ่มเหล่านี้จะเพิ่มหรือลดตัวเลขและอาจนําเลข 0 นําหน้าออก
ให้ใช้ type="text"
แทน ซึ่งจะไม่เปลี่ยนแป้นพิมพ์บนอุปกรณ์เคลื่อนที่ให้แสดงเฉพาะตัวเลข แต่ไม่เป็นไรเพราะเคล็ดลับถัดไปในการใช้ inputmode="numeric"
จะทำสิ่งนั้น
inputmode="numeric"
ใช้ inputmode="numeric"
เพื่อเปลี่ยนแป้นพิมพ์บนอุปกรณ์เคลื่อนที่เป็นตัวเลขเท่านั้น
บางเว็บไซต์ใช้ type="tel"
สำหรับช่องป้อน OTP เนื่องจากจะเปลี่ยนแป้นพิมพ์บนอุปกรณ์เคลื่อนที่เป็นตัวเลขเท่านั้น (รวมถึง *
และ #
) เมื่อโฟกัส ก่อนหน้านี้มีการแฮ็กนี้เมื่อinputmode="numeric"
ยังไม่ได้รับการรองรับอย่างแพร่หลาย เนื่องจาก Firefox เริ่มรองรับ inputmode="numeric"
แล้ว คุณจึงไม่จำเป็นต้องใช้แฮ็ก type="tel"
ที่ไม่ถูกต้องในเชิงความหมาย
autocomplete="one-time-code"
แอตทริบิวต์ autocomplete
ช่วยให้คุณระบุสิทธิ์ที่เบราว์เซอร์ต้องมีเพื่อให้ความช่วยเหลือในการเติมข้อความอัตโนมัติ และแจ้งให้เบราว์เซอร์ทราบเกี่ยวกับประเภทข้อมูลที่คาดหวังในช่อง
เมื่อใช้ autocomplete="one-time-code"
เมื่อใดก็ตามที่ผู้ใช้ได้รับข้อความ SMS ขณะที่แบบฟอร์มเปิดอยู่ ระบบปฏิบัติการจะแยกวิเคราะห์ OTP ใน SMS ด้วยวิธีการเฮิวริสติก และแป้นพิมพ์จะแนะนำ OTP ให้ผู้ใช้ป้อน ซึ่งใช้ได้ใน Safari 12 ขึ้นไปบน iOS, iPadOS และ macOS เท่านั้น แต่เราขอแนะนําอย่างยิ่งให้ใช้ฟีเจอร์นี้ เนื่องจากเป็นวิธีที่ง่ายในการปรับปรุงประสบการณ์การใช้งาน OTP ทาง SMS ในแพลตฟอร์มเหล่านั้น
autocomplete="one-time-code"
ช่วยปรับปรุงประสบการณ์ของผู้ใช้ แต่คุณยังทำได้อีกมากมายโดยตรวจสอบว่าข้อความ SMS เป็นไปตามรูปแบบข้อความที่เชื่อมโยงกับต้นทาง
จัดรูปแบบข้อความ SMS
ปรับปรุงประสบการณ์ของผู้ใช้ในการป้อน OTP โดยปรับให้สอดคล้องกับข้อกำหนดของรหัสแบบครั้งเดียวที่ผูกกับต้นทางซึ่งส่งผ่าน SMS
กฎการจัดรูปแบบนั้นง่ายมาก เพียงใส่โดเมนของผู้รับต่อท้ายข้อความ SMS โดยนำหน้าด้วย @
และใส่ OTP โดยนำหน้าด้วย #
เช่น
Your OTP is 123456
@web-otp.glitch.me #123456
การใช้รูปแบบมาตรฐานสำหรับข้อความ OTP จะทำให้การดึงรหัสจากข้อความดังกล่าวง่ายและน่าเชื่อถือยิ่งขึ้น การเชื่อมโยงรหัส OTP กับเว็บไซต์จะทำให้หลอกให้ผู้ใช้ระบุรหัสแก่เว็บไซต์ที่เป็นอันตรายได้ยากขึ้น
การใช้รูปแบบนี้มีประโยชน์ 2 อย่างดังนี้
- OTP จะเชื่อมโยงกับโดเมน หากผู้ใช้อยู่ในโดเมนอื่นนอกเหนือจากโดเมนที่ระบุในข้อความ SMS คําแนะนํา OTP จะไม่ปรากฏ ซึ่งจะช่วยลดความเสี่ยงจากการโจมตีแบบฟิชชิงและการลักลอบใช้บัญชีที่อาจเกิดขึ้น
- ตอนนี้เบราว์เซอร์จะดึงข้อมูล OTP ได้อย่างน่าเชื่อถือโดยไม่ต้องอาศัยวิธีการเดาที่ไม่แน่นอนและลึกลับ
เมื่อเว็บไซต์ใช้ autocomplete="one-time-code"
ทาง Safari ที่ใช้ iOS 14 ขึ้นไปจะแนะนำ OTP ตามกฎข้างต้น
รูปแบบข้อความ SMS นี้ยังเป็นประโยชน์ต่อเบราว์เซอร์อื่นๆ นอกเหนือจาก Safari ด้วย Chrome, Opera และ Vivaldi ใน Android ยังรองรับกฎเกี่ยวกับรหัสแบบครั้งเดียวที่เชื่อมโยงกับต้นทางด้วย WebOTP API ด้วย แต่ไม่ผ่าน autocomplete="one-time-code"
ใช้ WebOTP API
WebOTP API ให้สิทธิ์เข้าถึง OTP ที่ได้รับในข้อความ SMS เมื่อเรียกใช้ navigator.credentials.get()
ที่มีประเภท otp
(OTPCredential
) โดยที่ transport
รวม sms
ไว้ด้วย เว็บไซต์จะรอ SMS ที่เป็นไปตามโค้ดแบบครั้งเดียวที่เชื่อมโยงกับต้นทางเพื่อส่งให้ผู้ใช้และอนุญาตให้เข้าถึง เมื่อส่ง OTP ไปยัง JavaScript แล้ว เว็บไซต์จะใช้ OTP ในแบบฟอร์มหรือ POST ไปยังเซิร์ฟเวอร์โดยตรงได้
navigator.credentials.get({
otp: {transport:['sms']}
})
.then(otp => input.value = otp.code);
ดูวิธีใช้ WebOTP API โดยละเอียดในยืนยันหมายเลขโทรศัพท์บนเว็บด้วย WebOTP API หรือคัดลอกและวางข้อมูลโค้ดต่อไปนี้ (ตรวจสอบว่าองค์ประกอบ <form>
มีแอตทริบิวต์ action
และ method
ที่ตั้งค่าอย่างถูกต้อง)
// Feature detection
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', e => {
const input = document.querySelector('input[autocomplete="one-time-code"]');
if (!input) return;
// Cancel the WebOTP API if the form is submitted manually.
const ac = new AbortController();
const form = input.closest('form');
if (form) {
form.addEventListener('submit', e => {
// Cancel the WebOTP API.
ac.abort();
});
}
// Invoke the WebOTP API
navigator.credentials.get({
otp: { transport:['sms'] },
signal: ac.signal
}).then(otp => {
input.value = otp.code;
// Automatically submit the form when an OTP is obtained.
if (form) form.submit();
}).catch(err => {
console.log(err);
});
});
}
รูปภาพโดย Jason Leung จาก Unsplash