Secure Text Entry คือโหมดการป้อนข้อความใน Android ซึ่งอักขระที่ป้อนจะแสดงในรูปแบบที่ซ่อนอยู่ (จุดหรือเครื่องหมายดอกจัน) แทนที่จะเป็นอักขระจริง โหมดนี้ใช้สำหรับฟิลด์รหัสผ่าน รหัส PIN รหัส CVV และข้อมูลลับอื่น ๆ Secure Text Entry ไม่เพียงแค่ปกป้องข้อมูลจากการสอดส่องทางสายตา แต่ยังป้องกันการรั่วไหลผ่านภาพหน้าจอ การบันทึกหน้าจอ และฟีเจอร์การแก้ไขอัตโนมัติ ตาม Android Security Best Practices (2026) การป้อนแบบซ่อนเป็นข้อกำหนดบังคับสำหรับแอปพลิเคชันที่ประมวลผลข้อมูลการยืนยันตัวตนของผู้ใช้
ประเด็นสำคัญ
Secure Text Entry (การป้อนข้อความที่ได้รับการป้องกัน) คือฟีเจอร์ของ Android ที่แทนที่การแสดงอักขระที่ป้อนแต่ละตัวด้วยอักขระปิดบัง โดยปกติคือจุด (•) หรือเครื่องหมายดอกจัน (*) ซึ่งป้องกันการอ่านรหัสผ่านผ่านไหล่ (shoulder surfing) และซ่อนข้อมูลที่ป้อนจากสายตาที่สอดรู้สอดเห็น ฟีเจอร์นี้ยังรู้จักในชื่อการปิดบังรหัสผ่านและเป็นแนวทางปฏิบัติมาตรฐานในแอปพลิเคชันมือถือ
แตกต่างจาก iOS ที่ Secure Text Entry เป็นการตั้งค่า UITextField แยกต่างหาก ใน Android ฟีเจอร์นี้จะเปิดใช้งานผ่านแอตทริบิวต์ inputType ด้วยรูปแบบ PASSWORD เมื่อ EditText ได้รับ inputType="textPassword" มันจะใช้ PasswordTransformationMethod โดยอัตโนมัติ — คลาสที่รับผิดชอบในการแทนที่อักขระ เมื่อป้อนอักขระใหม่แต่ละตัว EditText จะแทนที่มันทันทีด้วยอักขระปิดบังผ่านกลไกอินเทอร์เฟส TransformationMethod
ตาม Android Source Code (AOSP, 2026) การนำ PasswordTransformationMethod ไปใช้ใช้คลาส TextPaint ในการเรนเดอร์อักขระปิดบัง ขนาดของอักขระปิดบังจะตรงกับขนาดฟอนต์ของฟิลด์ ซึ่งป้องกันการรั่วไหลของข้อมูลผ่านความยาวของคำ — อักขระทั้งหมดจะมีความกว้างเท่ากัน ซึ่งสำคัญสำหรับการป้องกันการโจมตีที่อิงจากการวิเคราะห์ความยาวของข้อมูลที่ป้อน
<!-- Basic Secure Text Entry example -->
@+id/etPassword
android:layout_width="match_parent"
android:hint="Enter password"
android:inputType="textPassword"
android:maxLength="64"
android:importantForAutofill="yes" />
กลไกของ Secure Text Entry ใน Android ขึ้นอยู่กับอินเทอร์เฟส TransformationMethod ที่กำหนดไว้ในแพ็คเกจ android.text.method PasswordTransformationMethod คือการนำไปใช้ในตัวที่แทนที่เมธอด getTransformation() โดยส่งคืนลำดับอักขระที่ถูกแทนที่สำหรับการแสดงผล ข้อความต้นฉบับใน Editable จะไม่เปลี่ยนแปลง — เฉพาะการแสดงผลทางสายตาเท่านั้นที่ถูกปรับเปลี่ยน
เมื่อผู้ใช้ป้อนอักขระ EditText จะเรียก dispatchEvent และส่งอักขระไปยัง InputConnection ซึ่งเพิ่มเข้าไปใน Editable จากนั้น EditText จะเรียกเมธอด getTransformation() ของ TransformationMethod ปัจจุบัน ซึ่งรับ CharSequence ต้นฉบับและส่งคืน SpannableString พร้อมอักขระปิดบัง SpannableString นี้จะถูกเรนเดอร์บนหน้าจอแทนที่ข้อความต้นฉบับ คุณลักษณะสำคัญคือการแปลงค่าไม่ได้เปลี่ยนแปลงเนื้อหาของ Editable ดังนั้นการเรียก getText().toString() จะส่งคืนข้อความที่ป้อนจริง
ตาม Android Developers Reference (2026) PasswordTransformationMethod จะเพิ่ม MetricAffectingSpan ให้กับแต่ละอักขระ ซึ่งแทนที่กลิฟด้วยจุด สแปนเหล่านี้ไม่มีผลต่อความยาวข้อความ ดังนั้นเคอร์เซอร์และตำแหน่งป้อนข้อมูลจะถูกเก็บรักษาไว้อย่างถูกต้องแม้จะแสดงแบบซ่อน นอกจากนี้ยังมี VisiblePasswordTransformationMethod ซึ่งแสดงอักขระสุดท้ายที่ป้อนในช่วงเวลาสั้น ๆ (คล้ายกับ iOS)
// PasswordTransformationMethod - built-in masking
editText.transformationMethod = PasswordTransformationMethod.getInstance()
// VisiblePasswordTransformationMethod - shows last char
editText.transformationMethod = VisiblePasswordTransformationMethod.getInstance()
การสลับการมองเห็น (password visibility toggle) คือฟีเจอร์ที่ช่วยให้ผู้ใช้สามารถแสดงรหัสผ่านที่ป้อนไว้ชั่วคราวเพื่อตรวจสอบก่อนส่งแบบฟอร์ม ใน Android ฟีเจอร์นี้ถูกนำไปใช้ผ่าน TextInputLayout ด้วยแอตทริบิวต์ app:endIconMode="password_toggle" เมื่อแตะไอคอนตา ฟิลด์จะสลับระหว่าง textPassword และ textVisiblePassword
การนำ password_toggle ไปใช้ใน TextInputLayout จะเปลี่ยน inputType ของ EditText ภายในโดยอัตโนมัติและทำให้ไอคอนเคลื่อนไหว (ตาเปิด/ปิด) สิ่งสำคัญที่ต้องจำคือในระหว่างการสลับนี้ ตำแหน่งเคอร์เซอร์อาจถูกรีเซ็ต ดังนั้น TextInputLayout จะบันทึกและกู้คืนตำแหน่งหลังการเปลี่ยนโหมด นอกจากนี้ เมื่อสลับไปยังรหัสผ่านที่มองเห็นได้ การแก้ไขอัตโนมัติและคำแนะนำจะไม่ถูกเปิดใช้งาน — ใช้ TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ไม่ใช่ข้อความปกติ
ตาม Material Design Guidelines (2025) ไอคอนแสดงรหัสผ่านควรมองเห็นได้ตลอดเวลา ไม่ใช่เฉพาะเมื่อฟิลด์ถูกโฟกัส ผู้ใช้ควรสามารถตรวจสอบรหัสผ่านได้ทุกเวลา ไอคอนไม่ควรซ่อนรหัสผ่านโดยอัตโนมัติหลังจากเวลาที่กำหนด — เฉพาะเมื่อผู้ใช้ดำเนินการเท่านั้น
<!-- TextInputLayout with password toggle -->
@+id/tilPassword
android:layout_width="match_parent"
app:endIconMode="password_toggle"
app:passwordToggleTint="@color/primary">
@+id/etPassword
android:inputType="textPassword"
android:hint="Password" />
</com.google.android.material.textfield.TextInputLayout>
การตั้งค่า Secure Text Entry ด้วยโปรแกรมใน Kotlin ทำได้โดยการตั้งค่า inputType หรือผ่าน setTransformationMethod() ทั้งสองวิธีนำไปสู่ผลลัพธ์เดียวกันแต่แตกต่างกันในรายละเอียด การตั้งค่า inputType จะกำหนดค่าการแก้ไขอัตโนมัติและคำแนะนำเพิ่มเติม ในขณะที่ setTransformationMethod มีผลเฉพาะกับการแสดงอักขระเท่านั้น
// Programmatic password visibility toggle
fun togglePasswordVisibility(til: TextInputLayout) {
val editText = til.editText ?: return
val currentType = editText.inputType
val isPassword = (currentType and
InputType.TYPE_TEXT_VARIATION_PASSWORD) != 0
if (isPassword) {
editText.inputType = InputType.TYPE_CLASS_TEXT or
InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
} else {
editText.inputType = InputType.TYPE_CLASS_TEXT or
InputType.TYPE_TEXT_VARIATION_PASSWORD
}
// Restore cursor position
val cursorPos = editText.selectionStart
editText.setSelection(maxOf(0, cursorPos))
}
// Custom masking — shows only last 4 chars
class PartialPasswordTransformation : TransformationMethod {
override fun getTransformation(source: CharSequence?,
view: View?): CharSequence {
val text = source?.toString() ?: ""
if (text.length <= 4) return text
val dots = "\u2022".repeat(text.length - 4)
return dots + text.substring(text.length - 4)
}
override fun onFocusChanged(view: View?,
sourceText: CharSequence?,
focused: Boolean,
direction: Int,
previouslyFocusedRect: android.graphics.Rect?) {}
}
Secure Text Entry ให้การป้องกันในหลายระดับ การปิดบังทางสายตาป้องกันการอ่านรหัสผ่านผ่านไหล่ (shoulder surfing) — วิธีการขโมยรหัสผ่านที่พบบ่อยที่สุดในที่สาธารณะ การปิดการแก้ไขอัตโนมัติป้องกันไม่ให้รหัสผ่านถูกบันทึกในพจนานุกรมของผู้ใช้ ซึ่งช่วยลดการรั่วไหลผ่านการป้อนแบบคาดเดา การป้องกันภาพหน้าจอ (หากเปิดใช้ FLAG_SECURE) ป้องกันไม่ให้แอปพลิเคชันอื่นบันทึกเนื้อหาของฟิลด์
อย่างไรก็ตาม Secure Text Entry ไม่ใช่การป้องกันที่สมบูรณ์ การโจมตีผ่านการดักจับการป้อนข้อมูล (keylogging) ในระดับระบบสามารถรับอักขระจริงจาก InputConnection แอปพลิเคชันที่เป็นอันตรายพร้อมบริการการเข้าถึงสามารถอ่านเนื้อหา EditText ได้แม้ว่าอักขระจะถูกซ่อนบนหน้าจอ นอกจากนี้ การดักฟัง SSL ระหว่างการส่งข้อมูลไปยังเซิร์ฟเวอร์อาจเปิดเผยรหัสผ่านหากไม่ได้ใช้ HTTPS ด้วยการตรวจสอบใบรับรองที่เหมาะสม
ตาม OWASP Mobile Security Testing Guide (2025) สำหรับการป้องกันรหัสผ่านสูงสุดใน Android แนะนำให้: ใช้ inputType="textPassword" + ปิดการใช้งาน autofill สำหรับฟิลด์สำคัญ ไม่เก็บรหัสผ่านในแคชหน่วยความจำนานเกินจำเป็น ล้างฟิลด์รหัสผ่านเมื่อย่อแอปพลิเคชัน (onPause/onStop) ใช้การปิดบังแม้ในระหว่างการแสดงรหัสผ่านชั่วคราว
| ระดับการป้องกัน | Secure Text Entry | มาตรการเพิ่มเติม |
|---|---|---|
| การสอดส่องทางสายตา | การปิดบังอักขระ | การยืนยันตัวตนด้วยไบโอเมตริก, หลีกเลี่ยง shoulder surfing |
| ภาพหน้าจอ | บางส่วน (ขึ้นอยู่กับการนำไปใช้) | FLAG_SECURE บน Window |
| Keylogging | ไม่ป้องกัน | ใช้ IME ที่มีการป้อนข้อมูลอย่างปลอดภัย |
| การแก้ไขอัตโนมัติ/พจนานุกรม | ปิดการใช้งาน | ปิดโดยค่าเริ่มต้นสำหรับรหัสผ่าน |
| การดักจับเครือข่าย | ไม่ป้องกัน | HTTPS พร้อมการปักหมุดใบรับรอง |
นักพัฒนา Android ควรปฏิบัติตาม แนวทางหลัก หลายประการเมื่อทำงานกับการป้อนข้อมูลแบบซ่อน หนึ่ง ใช้ TextInputLayout ด้วย endIconMode="password_toggle" สำหรับฟิลด์รหัสผ่านเสมอ — นี่คือมาตรฐาน Material Design สมัยใหม่ สอง อย่าปิดการใช้งานความสามารถในการแสดงรหัสผ่าน — ผู้ใช้ควรสามารถตรวจสอบสิ่งที่ป้อนได้ โดยเฉพาะบนอุปกรณ์มือถือที่มีแป้นพิมพ์ขนาดเล็ก
Secure Text Entry ยังต้องการการกำหนดค่าการเติมข้อความอัตโนมัติที่เหมาะสม สำหรับฟิลด์รหัสผ่าน ให้ระบุ autofillHints="password" หรือ autofillHints="newPassword" เสมอ เพื่อให้ตัวจัดการรหัสผ่านสามารถเติมและบันทึกข้อมูลได้อย่างถูกต้อง สำหรับฟิลด์ยืนยันรหัสผ่านใหม่ ให้ใช้ autofillHints="newPassword" เพื่อให้ระบบไม่แนะนำให้เติมด้วยรหัสผ่านที่บันทึกไว้ปัจจุบัน
// Full password field with autofill and cleanup
class SecurePasswordField {
private fun setupPasswordField(til: TextInputLayout) {
val editText = til.editText ?: return
editText.inputType = InputType.TYPE_CLASS_TEXT or
InputType.TYPE_TEXT_VARIATION_PASSWORD
editText.setAutofillHints(View.AUTOFILL_HINT_PASSWORD>)
editText.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES
}
fun clearOnPause(editText: EditText) {
editText.text?.clear()
}
}
คำถามที่พบบ่อย
textPassword ซ่อนอักขระที่ป้อนทั้งหมดและปิดการแก้ไขอัตโนมัติ textVisiblePassword ก็ปิดการแก้ไขอัตโนมัติเช่นกันแต่แสดงอักขระอย่างชัดเจน textVisiblePassword ใช้เมื่อสลับการมองเห็นรหัสผ่าน — มันไม่ใช่ข้อความปกติ เนื่องจากการแก้ไขอัตโนมัติและคำแนะนำยังคงถูกปิดเพื่อความปลอดภัย
ได้ สร้างคลาสกำหนดเองที่ implements อินเทอร์เฟส TransformationMethod แทนที่เมธอด getTransformation() ที่ส่งคืน CharSequence พร้อมอักขระแทนที่ที่ต้องการ ตั้งค่าผ่าน editText.transformationMethod = CustomPasswordTransformation() จำไว้ว่าอักขระต้องเป็นแบบmonospaced เพื่อความปลอดภัย
บนอุปกรณ์มือถือที่มีหน้าจอขนาดเล็กและแป้นพิมพ์สัมผัส โอกาสเกิดข้อผิดพลาดเมื่อป้อนรหัสผ่านสูงกว่าเดสก์ท็อปอย่างมาก ความสามารถในการตรวจสอบรหัสผ่านที่ป้อนช่วยลดข้อผิดพลาดในการป้อนและลดจำนวนคำขอรีเซ็ตรหัสผ่าน ซึ่งปรับปรุงประสบการณ์ผู้ใช้และลดภาระการสนับสนุน
ตั้งค่าแฟล็ก FLAG_SECURE บนหน้าต่าง Activity หรือ Dialog: window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) ซึ่งป้องกันภาพหน้าจอและการบันทึกหน้าจอสำหรับทั้งหน้าต่าง อย่างไรก็ตาม โปรดทราบว่าสิ่งนี้จะปิดการใช้งานภาพหน้าจอสำหรับเนื้อหาทั่วไปด้วย ซึ่งอาจไม่เป็นที่ต้องการ
เริ่มจาก Android 8.0 (API 26) Autofill Framework จะตรวจจับฟิลด์รหัสผ่านโดยอัตโนมัติจาก inputType สำหรับการทำงานที่ถูกต้อง ให้ตั้งค่า importantForAutofill="yes" และระบุ autofillHints ("password", "newPassword", "emailAddress") Gboard และตัวจัดการรหัสผ่านใช้แอตทริบิวต์เหล่านี้เพื่อแนะนำรหัสผ่านที่บันทึกไว้
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ