Secure Text Entry — nó là gì, bảo vệ nhập liệu và mật khẩu trong Android

Tác giả: IT Sectr Đã đăng: 2026-07-07 Thời gian đọc: 9 phút

Secure Text Entry là chế độ nhập văn bản trong Android mà các ký tự được nhập được hiển thị ở dạng ẩn (dấu chấm hoặc dấu sao) thay vì các ký tự thực tế. Chế độ này được sử dụng cho các trường mật khẩu, mã PIN, mã CVV và thông tin bảo mật khác. Secure Text Entry không chỉ bảo vệ dữ liệu khỏi bị chặn trực quan mà còn ngăn rò rỉ qua ảnh chụp màn hình, ghi màn hình và các tính năng tự động sửa. Theo Android Security Best Practices (2026), nhập ẩn là yêu cầu bắt buộc đối với các ứng dụng xử lý dữ liệu xác thực người dùng.

Những điểm chính

  • Secure Text Entry — chế độ nhập ẩn hiển thị dấu chấm thay vì ký tự khi nhập mật khẩu.
  • Kích hoạt — qua inputType="textPassword" trong XML hoặc TYPE_TEXT_VARIATION_PASSWORD trong mã.
  • Bảo vệ — ngăn chặn trực quan, ảnh chụp màn hình và rò rỉ qua tự động sửa/từ điển.
  • TransformationMethod — cơ chế Android thay thế hiển thị ký tự bằng ký hiệu ẩn.
  • Chuyển đổi hiển thị — khả năng hiển thị mật khẩu qua endIconMode="password_toggle" trong TextInputLayout.

Secure Text Entry trong Android là gì

Secure Text Entry (nhập văn bản được bảo vệ) là tính năng Android thay thế hiển thị mỗi ký tự được nhập bằng ký tự che giấu, thường là dấu chấm (•) hoặc dấu sao (*). Điều này ngăn đọc mật khẩu qua vai (shoulder surfing) và ẩn dữ liệu nhập khỏi những con mắt tò mò. Tính năng này còn được gọi là che giấu mật khẩu và là thông lệ tiêu chuẩn trong các ứng dụng di động.

Không giống iOS, nơi Secure Text Entry là cài đặt riêng của UITextField, trong Android tính năng này được kích hoạt qua thuộc tính inputType với biến thể PASSWORD. Khi EditText nhận inputType="textPassword", nó tự động áp dụng PasswordTransformationMethod — lớp chịu trách nhiệm thay thế ký tự. Khi mỗi ký tự mới được nhập, EditText ngay lập tức thay thế nó bằng ký tự che giấu qua cơ chế giao diện TransformationMethod.

Theo Android Source Code (AOSP, 2026), việc triển khai PasswordTransformationMethod sử dụng lớp TextPaint để hiển thị các ký tự che giấu. Kích thước của ký tự che giấu khớp với kích thước phông chữ của trường, ngăn rò rỉ thông tin qua độ dài từ — tất cả các ký tự trông giống nhau về chiều rộng. Điều này quan trọng để bảo vệ chống lại các cuộc tấn công dựa trên phân tích độ dài dữ liệu nhập.

xml
<!-- 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" />

Cách Secure Text Entry hoạt động

Cơ chế Secure Text Entry trong Android dựa trên giao diện TransformationMethod, được định nghĩa trong gói android.text.method. PasswordTransformationMethod là một triển khai tích hợp ghi đè phương thức getTransformation(), trả về một chuỗi ký tự đã được thay thế để hiển thị. Văn bản gốc trong Editable không thay đổi — chỉ có biểu diễn trực quan của nó bị thay đổi.

Khi người dùng nhập một ký tự, EditText gọi dispatchEvent và chuyển ký tự đến InputConnection, thêm nó vào Editable. Sau đó EditText gọi phương thức getTransformation() của TransformationMethod hiện tại, lấy CharSequence gốc và trả về SpannableString với các ký tự che giấu. SpannableString này được hiển thị trên màn hình thay vì văn bản gốc. Đặc điểm chính là việc biến đổi không thay đổi nội dung Editable, do đó gọi getText().toString() trả về văn bản thực tế đã nhập.

Theo Android Developers Reference (2026), PasswordTransformationMethod thêm MetricAffectingSpan vào mỗi ký tự, thay thế glyph bằng một dấu chấm. Các span này không ảnh hưởng đến độ dài văn bản, do đó con trỏ và vị trí nhập được giữ chính xác ngay cả khi hiển thị ẩn. VisiblePasswordTransformationMethod cũng tồn tại, hiển thị ký tự cuối cùng được nhập trong thời gian ngắn (tương tự iOS).

kotlin
// PasswordTransformationMethod - built-in masking
editText.transformationMethod = PasswordTransformationMethod.getInstance()

// VisiblePasswordTransformationMethod - shows last char
editText.transformationMethod = VisiblePasswordTransformationMethod.getInstance()

Chuyển đổi hiển thị mật khẩu

Chuyển đổi hiển thị (password visibility toggle) là tính năng cho phép người dùng tạm thời hiển thị mật khẩu đã nhập để kiểm tra trước khi gửi biểu mẫu. Trong Android, tính năng này được triển khai qua TextInputLayout với thuộc tính app:endIconMode="password_toggle". Khi chạm vào biểu tượng mắt, trường chuyển đổi giữa textPassword và textVisiblePassword.

Việc triển khai password_toggle trong TextInputLayout tự động thay đổi inputType của EditText nội bộ và tạo hiệu ứng cho biểu tượng (mắt mở/đóng). Điều quan trọng cần nhớ là trong quá trình chuyển đổi này, vị trí con trỏ có thể bị đặt lại, do đó TextInputLayout lưu và khôi phục vị trí sau khi thay đổi chế độ. Ngoài ra, khi chuyển sang mật khẩu hiển thị, tự động sửa và gợi ý không được bật — TYPE_TEXT_VARIATION_VISIBLE_PASSWORD được sử dụng, không phải văn bản thông thường.

Theo Material Design Guidelines (2025), biểu tượng hiển thị mật khẩu phải luôn hiển thị, không chỉ khi trường được tập trung. Người dùng phải có thể kiểm tra mật khẩu bất kỳ lúc nào. Biểu tượng không nên tự động ẩn mật khẩu sau một thời gian nhất định — chỉ khi người dùng thao tác.

xml
<!-- 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>

Cấu hình lập trình Secure Text Entry

Thiết lập lập trình Secure Text Entry trong Kotlin được thực hiện bằng cách đặt inputType hoặc qua setTransformationMethod(). Cả hai cách tiếp cận đều dẫn đến cùng kết quả nhưng khác nhau về chi tiết. Đặt inputType còn cấu hình thêm tự động sửa và gợi ý, trong khi setTransformationMethod chỉ ảnh hưởng đến hiển thị ký tự.

Ví dụ chuyển đổi mật khẩu qua TextInputLayout

kotlin
// 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))
}

TransformationMethod tùy chỉnh

kotlin
// 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?) {}
}

Các khía cạnh bảo mật của nhập ẩn

Secure Text Entry cung cấp bảo vệ ở nhiều cấp độ. Che giấu trực quan ngăn đọc mật khẩu qua vai (shoulder surfing) — phương pháp đánh cắp mật khẩu phổ biến nhất ở nơi công cộng. Vô hiệu hóa tự động sửa ngăn mật khẩu được lưu trong từ điển người dùng, loại bỏ rò rỉ qua nhập dự đoán. Bảo vệ khỏi ảnh chụp màn hình (nếu FLAG_SECURE được bật) ngăn các ứng dụng khác chụp nội dung trường.

Tuy nhiên, Secure Text Entry không phải là bảo vệ hoàn toàn. Các cuộc tấn công qua chặn nhập liệu (keylogging) ở cấp hệ thống có thể lấy các ký tự thực tế từ InputConnection. Các ứng dụng độc hại có dịch vụ trợ năng có thể đọc nội dung EditText ngay cả khi ký tự bị ẩn trên màn hình. Ngoài ra, SSL sniffing trong quá trình truyền dữ liệu đến máy chủ có thể lộ mật khẩu nếu không sử dụng HTTPS với xác thực chứng chỉ phù hợp.

Theo OWASP Mobile Security Testing Guide (2025), để bảo vệ mật khẩu tối đa trong Android, khuyến nghị: sử dụng inputType="textPassword" + vô hiệu hóa autofill cho các trường quan trọng; không lưu mật khẩu trong bộ nhớ lâu hơn cần thiết; xóa trường mật khẩu khi thu nhỏ ứng dụng (onPause/onStop); sử dụng che giấu ngay cả khi hiển thị mật khẩu ngắn.

Cấp độ bảo vệSecure Text EntryBiện pháp bổ sung
Chặn trực quanChe giấu ký tựXác thực sinh trắc học, tránh shoulder surfing
Ảnh chụp màn hìnhMột phần (tùy thuộc triển khai)FLAG_SECURE trên Window
KeyloggingKhông bảo vệSử dụng IME với nhập liệu an toàn
Tự động sửa/từ điểnVô hiệu hóavô hiệu hóa mặc định cho mật khẩu
Chặn mạngKhông bảo vệHTTPS với ghim chứng chỉ

Thực tiễn tốt nhất cho Secure Text Entry

Các nhà phát triển Android nên tuân theo một số thực tiễn chính khi làm việc với nhập ẩn. Thứ nhất, luôn sử dụng TextInputLayout với endIconMode="password_toggle" cho trường mật khẩu — đây là tiêu chuẩn Material Design hiện đại. Thứ hai, không vô hiệu hóa khả năng hiển thị mật khẩu — người dùng phải có thể kiểm tra những gì họ đã nhập, đặc biệt trên thiết bị di động với bàn phím nhỏ.

Secure Text Entry cũng yêu cầu cấu hình tự động điền phù hợp. Đối với trường mật khẩu, luôn chỉ định autofillHints="password" hoặc autofillHints="newPassword" để trình quản lý mật khẩu có thể điền và lưu dữ liệu chính xác. Đối với trường xác nhận mật khẩu mới, sử dụng autofillHints="newPassword" để hệ thống không đề xuất điền nó với mật khẩu đã lưu hiện tại.

  • TextInputLayout — sử dụng Material Design TextInputLayout với endIconMode để chuyển đổi hiển thị.
  • Autofill — thêm autofillHints="password" và importantForAutofill="yes" để hỗ trợ trình quản lý.
  • Xóa — xóa trường mật khẩu khi thu nhỏ ứng dụng (onPause/onStop).
  • Độ dài — không giới hạn độ dài mật khẩu quá nghiêm ngặt (tối thiểu 8 ký tự, không có tối đa cứng nhắc).
  • Sinh trắc học — cung cấp đăng nhập sinh trắc học (BiometricPrompt) như thay thế cho nhập mật khẩu thủ công.
kotlin
// 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()
    }
}

Các câu hỏi thường gặp

Sự khác biệt giữa textPassword và textVisiblePassword là gì?

textPassword ẩn tất cả các ký tự đã nhập và vô hiệu hóa tự động sửa. textVisiblePassword cũng vô hiệu hóa tự động sửa nhưng hiển thị ký tự rõ ràng. textVisiblePassword được sử dụng khi chuyển đổi hiển thị mật khẩu — đó không phải văn bản thông thường, vì tự động sửa và gợi ý vẫn bị vô hiệu hóa vì bảo mật.

Tôi có thể tạo ký tự tùy chỉnh để che giấu mật khẩu không?

Có, hãy tạo một lớp tùy chỉnh triển khai giao diện TransformationMethod. Ghi đè phương thức getTransformation() trả về CharSequence với ký tự thay thế mong muốn. Đặt nó qua editText.transformationMethod = CustomPasswordTransformation(). Hãy nhớ rằng ký tự phải có độ rộng cố định vì bảo mật.

Tại sao không nên vô hiệu hóa khả năng hiển thị mật khẩu?

Trên thiết bị di động với màn hình nhỏ và bàn phím cảm ứng, xác suất lỗi khi nhập mật khẩu cao hơn đáng kể so với máy tính để bàn. Khả năng kiểm tra mật khẩu đã nhập giảm lỗi nhập liệu và giảm số lượng yêu cầu đặt lại mật khẩu, cải thiện trải nghiệm người dùng và giảm tải hỗ trợ.

Làm thế nào để bảo vệ mật khẩu khỏi ảnh chụp màn hình ứng dụng?

Đặt cờ FLAG_SECURE trên cửa sổ Activity hoặc Dialog: window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE). Điều này ngăn chụp màn hình và ghi màn hình cho toàn bộ cửa sổ. Tuy nhiên, lưu ý rằng điều này cũng sẽ vô hiệu hóa ảnh chụp màn hình cho nội dung thông thường, điều này có thể không mong muốn.

Tự động điền hoạt động thế nào cho trường mật khẩu?

Bắt đầu từ Android 8.0 (API 26), Autofill Framework tự động phát hiện trường mật khẩu qua inputType. Để hoạt động chính xác, hãy đặt importantForAutofill="yes" và chỉ định autofillHints ("password", "newPassword", "emailAddress"). Gboard và trình quản lý mật khẩu sử dụng các thuộc tính này để đề xuất mật khẩu đã lưu.

Tổng kết

  • Secure Text Entry — chế độ nhập ẩn thay thế ký tự bằng ký hiệu che giấu (dấu chấm) qua PasswordTransformationMethod.
  • Kích hoạt — qua inputType="textPassword" hoặc thiết lập lập trình TYPE_TEXT_VARIATION_PASSWORD.
  • PasswordTransformationMethod — lớp Android tích hợp thay thế hiển thị ký tự mà không sửa đổi Editable.
  • Chuyển đổi hiển thị — được triển khai qua TextInputLayout với endIconMode="password_toggle" và TYPE_TEXT_VARIATION_VISIBLE_PASSWORD.
  • Bảo vệ — ngăn shoulder surfing, ảnh chụp màn hình (với FLAG_SECURE), tự động sửa và lưu từ điển.
  • Autofill — để hỗ trợ trình quản lý mật khẩu, thêm importantForAutofill và autofillHints="password".
  • Thực tiễn tốt nhất — sử dụng TextInputLayout, xóa trường khi thu nhỏ, không giới hạn độ dài mật khẩu nghiêm ngặt.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm