Secure Text Entry — co to jest, ochrona wprowadzania i hasła w Androidzie

Autor: IT Sectr Opublikowano: 2026-07-07 Czas czytania: 9 min

Secure Text Entry — to tryb wprowadzania tekstu w Androidzie, w którym wprowadzane znaki są wyświetlane w ukrytej formie (kropki lub gwiazdki) zamiast rzeczywistych znaków. Ten tryb jest stosowany w polach wprowadzania haseł, kodów PIN, kodów CVV i innych poufnych informacji. Secure Text Entry nie tylko chroni dane przed wizualnym przechwyceniem, ale także zapobiega wyciekom przez zrzuty ekranu, nagrania ekranu i funkcje autokorekty. Według Android Security Best Practices (2026), ukryte wprowadzanie jest obowiązkowym wymogiem dla aplikacji przetwarzających dane uwierzytelniające użytkowników.

Najważniejsze

  • Secure Text Entry — tryb ukrytego wprowadzania, wyświetlający kropki zamiast znaków podczas wpisywania hasła.
  • Aktywacja — przez inputType="textPassword" w XML lub TYPE_TEXT_VARIATION_PASSWORD w kodzie.
  • Ochrona — zapobiega wizualnemu przechwyceniu, zrzutom ekranu i wyciekom przez autokorektę/słownik.
  • TransformationMethod — mechanizm Androida zastępujący wyświetlanie znaków na ukryte.
  • Przełącznik widoczności — możliwość pokazania hasła przez endIconMode="password_toggle" w TextInputLayout.

Czym jest Secure Text Entry w Androidzie

Secure Text Entry (chronione wprowadzanie tekstu) — to funkcja Androida, która zastępuje wyświetlanie każdego wprowadzonego znaku maskującym symbolem, zazwyczaj kropką (•) lub gwiazdką (*). Zapobiega to odczytaniu hasła przez ramię (shoulder surfing) i ukrywa wprowadzane dane przed niepowołanymi oczami. Funkcja ta jest również znana jako maskowanie hasła i stanowi standardową praktykę w aplikacjach mobilnych.

W przeciwieństwie do iOS, gdzie Secure Text Entry jest oddzielnym ustawieniem UITextField, w Androidzie ta funkcja jest aktywowana przez atrybut inputType z wariacją PASSWORD. Gdy EditText otrzymuje inputType="textPassword", automatycznie stosuje PasswordTransformationMethod — klasę odpowiedzialną za zastępowanie znaków. Przy wprowadzaniu każdego nowego znaku EditText natychmiast zastępuje go maskującym symbolem poprzez mechanizm TransformationMethod interfejsu.

Według Android Source Code (AOSP, 2026), implementacja PasswordTransformationMethod używa klasy TextPaint do rysowania maskujących symboli. Rozmiar maskującego symbolu pokrywa się z rozmiarem czcionki pola, co zapobiega wyciekowi informacji przez długość słowa — wszystkie znaki wyglądają identycznie pod względem szerokości. Jest to ważne dla ochrony przed atakami opartymi na analizie długości wprowadzanych danych.

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

Jak działa Secure Text Entry

Mechanizm Secure Text Entry w Androidzie opiera się na interfejsie TransformationMethod, zdefiniowanym w pakiecie android.text.method. PasswordTransformationMethod — to wbudowana implementacja, która nadpisuje metodę getTransformation(), zwracając zastąpioną sekwencję znaków do wyświetlenia. Przy tym oryginalny tekst w Editable pozostaje niezmieniony — zmienia się tylko jego wizualna reprezentacja.

Gdy użytkownik wprowadza znak, EditText wywołuje dispatchEvent i przekazuje znak do InputConnection, który dodaje go do Editable. Następnie EditText wywołuje metodę getTransformation() bieżącego TransformationMethod, która otrzymuje oryginalny CharSequence i zwraca SpannableString z maskującymi symbolami. Ten SpannableString jest rysowany na ekranie zamiast oryginalnego tekstu. Kluczową cechą jest to, że samo przekształcenie nie zmienia zawartości Editable, dlatego przy wywołaniu getText().toString() zwracany jest rzeczywisty wprowadzony tekst.

Według Android Developers Reference (2026), PasswordTransformationMethod dodaje do każdego znaku MetricAffectingSpan, który zastępuje glif kropką. Te span-y nie wpływają na długość tekstu, dlatego kursor i pozycja wprowadzania są zachowane prawidłowo nawet przy ukrytym wyświetlaniu. Istnieje również VisiblePasswordTransformationMethod, który wyświetla ostatni wprowadzony znak przez krótki czas (podobnie jak w iOS).

kotlin
// PasswordTransformationMethod - wbudowane maskowanie
editText.transformationMethod = PasswordTransformationMethod.getInstance()

// VisiblePasswordTransformationMethod - pokazuje ostatni znak
editText.transformationMethod = VisiblePasswordTransformationMethod.getInstance()

Przełączanie widoczności hasła

Przełączanie widoczności (password visibility toggle) — to funkcja umożliwiająca użytkownikowi tymczasowe pokazanie wprowadzonego hasła w celu sprawdzenia go przed wysłaniem formularza. W Androidzie funkcja ta jest realizowana przez TextInputLayout z atrybutem app:endIconMode="password_toggle". Po kliknięciu ikony oka pole przełącza się między textPassword a textVisiblePassword.

Implementacja password_toggle w TextInputLayout automatycznie zmienia inputType wewnętrznego EditText i animuje ikonę (otwarte/zamknięte oko). Ważne jest, że przy takim przełączaniu pozycja kursora może się resetować, dlatego TextInputLayout zapisuje i przywraca pozycję po zmianie trybu. Również przy przełączaniu na widoczne hasło autokorekta i podpowiedzi nie są włączane — używany jest TYPE_TEXT_VARIATION_VISIBLE_PASSWORD, a nie zwykły text.

Według Material Design Guidelines (2025), ikona pokazywania hasła powinna być zawsze widoczna, a nie tylko gdy pole jest w focusie. Użytkownik powinien mieć możliwość sprawdzenia hasła w dowolnym momencie. Ikona nie powinna automatycznie ukrywać hasła po określonym czasie — tylko na działanie użytkownika.

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>

Programowa konfiguracja Secure Text Entry

Programowe ustawienie Secure Text Entry w Kotlin odbywa się przez ustawienie inputType lub przez setTransformationMethod(). Oba podejścia prowadzą do tego samego rezultatu, ale różnią się szczegółami. Ustawienie inputType dodatkowo konfiguruje autokorektę i podpowiedzi, podczas gdy setTransformationMethod wpływa tylko na wyświetlanie znaków.

Przykład przełącznika hasła przez TextInputLayout

kotlin
// Programowe przełączanie widoczności hasła
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
    }

    // Przywróć pozycję kursora
    val cursorPos = editText.selectionStart
    editText.setSelection(maxOf(0, cursorPos))
}

Niestandardowy TransformationMethod

kotlin
// Niestandardowe maskowanie — pokazuje tylko ostatnie 4 znaki
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?) {}
}

Aspekty bezpieczeństwa ukrytego wprowadzania

Secure Text Entry zapewnia ochronę na kilku poziomach. Wizualne maskowanie zapobiega odczytaniu hasła przez ramię (shoulder surfing) — najczęstszej metodzie kradzieży haseł w miejscach publicznych. Wyłączenie autokorekty zapobiega zapisaniu hasła w słowniku użytkownika, co eliminuje jego wyciek przez predykcyjne wprowadzanie. Ochrona przed zrzutami ekranu (jeśli włączono FLAG_SECURE) uniemożliwia innym aplikacjom przechwycenie zawartości pola.

Jednak Secure Text Entry nie stanowi pełnej ochrony. Ataki przez przechwycenie wprowadzania (keylogging) na poziomie systemu mogą uzyskać rzeczywiste znaki z InputConnection. Złośliwe aplikacje z usługą dostępności mogą czytać zawartość EditText, nawet jeśli znaki są ukryte na ekranie. Również SSL-sniffing przy przesyłaniu danych na serwer może ujawnić hasło, jeśli nie jest używany HTTPS z prawidłową walidacją certyfikatu.

Według OWASP Mobile Security Testing Guide (2025), dla maksymalnej ochrony haseł w Androidzie zaleca się: używanie inputType="textPassword" + wyłączenie autofill dla pól krytycznych; nieprzechowywanie hasła w pamięci dłużej niż to konieczne; czyszczenie pola hasła przy zwijaniu aplikacji (onPause/onStop); używanie maskowania nawet przy krótkotrwałym pokazywaniu hasła.

Poziom ochronySecure Text EntryDodatkowe środki
Przechwycenie wizualneMaskowanie znakówBiometric auth, unikaj shoulder surfing
Zrzuty ekranuczęściowa (zależy od implementacji)FLAG_SECURE na Window
KeyloggingNie chroniUżywaj IME z bezpiecznym wprowadzaniem
Autokorekta/słownikWyłączonawyłączona domyślnie dla password
Przechwycenie sieciNie chroniHTTPS z certificate pinning

Najlepsze praktyki Secure Text Entry

Deweloperzy Androida powinni przestrzegać kilku kluczowych praktyk podczas pracy z ukrytym wprowadzaniem. Po pierwsze, zawsze używaj TextInputLayout z endIconMode="password_toggle" dla pól hasła — to nowoczesny standard Material Design. Po drugie, nie wyłączaj możliwości pokazania hasła — użytkownik powinien mieć możliwość sprawdzenia, co wprowadził, szczególnie na urządzeniach mobilnych z małą klawiaturą.

Secure Text Entry wymaga również prawidłowej konfiguracji autouzupełniania. Dla pól hasła koniecznie określ autofillHints="password" lub autofillHints="newPassword", aby menedżery haseł mogły poprawnie wypełniać i zapisywać dane. Dla pola potwierdzenia nowego hasła używaj autofillHints="newPassword", aby system nie proponował wypełnienia go bieżącym zapisanym hasłem.

  • TextInputLayout — używaj Material Design TextInputLayout z endIconMode dla przełącznika widoczności.
  • Autofill — dodawaj autofillHints="password" i importantForAutofill="yes" dla wsparcia menedżerów.
  • Czyszczenie — czyść pole hasła przy zwijaniu aplikacji (onPause/onStop).
  • Długość — nie ograniczaj długości hasła zbyt restrykcyjnie (minimum 8 znaków, bez sztywnego maksimum).
  • Biometria — oferuj logowanie biometryczne (BiometricPrompt) jako alternatywę dla ręcznego wprowadzania hasła.
kotlin
// Pełne pole hasła z autouzupełnianiem i czyszczeniem
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()
    }
}

Często zadawane pytania

Jaka jest różnica między textPassword a textVisiblePassword?

textPassword ukrywa wszystkie wprowadzane znaki i wyłącza autokorektę. textVisiblePassword również wyłącza autokorektę, ale pokazuje znaki w otwartej formie. textVisiblePassword jest używany przy przełączaniu widoczności hasła — to nie zwykły text, ponieważ autokorekta i podpowiedzi pozostają wyłączone dla bezpieczeństwa.

Czy można zrobić niestandardowy symbol do maskowania hasła?

Tak, utwórz niestandardową klasę implementującą interfejs TransformationMethod. Nadpisz metodę getTransformation(), zwracającą CharSequence z potrzebnym symbolem zastępczym. Ustaw ją przez editText.transformationMethod = CustomPasswordTransformation(). Pamiętaj, że symbol powinien być monotypiczny dla bezpieczeństwa.

Dlaczego nie zaleca się wyłączania możliwości pokazania hasła?

Na urządzeniach mobilnych z małymi ekranami i klawiaturą dotykową prawdopodobieństwo błędu przy wprowadzaniu hasła jest znacznie wyższe niż na desktopie. Możliwość sprawdzenia wprowadzonego hasła zmniejsza liczbę błędów wprowadzania i redukuje liczbę próśb o odzyskanie hasła, co poprawia doświadczenie użytkownika i zmniejsza obciążenie wsparcia.

Jak chronić hasło przed zrzutami ekranu aplikacji?

Ustaw flagę FLAG_SECURE na okno Activity lub Dialog: window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE). Zapobiegnie to tworzeniu zrzutów ekranu i nagrywaniu ekranu dla całego okna. Należy jednak pamiętać, że wyłączy to również zrzuty ekranu dla zwykłej treści, co może być niepożądane.

Jak działa autofill dla pól password?

Począwszy od Android 8.0 (API 26), Autofill Framework automatycznie wykrywa pola password po inputType. Dla prawidłowego działania ustaw importantForAutofill="yes" i określ autofillHints ("password", "newPassword", "emailAddress"). Gboard i menedżery haseł używają tych atrybutów do proponowania zapisanych haseł.

Podsumowanie

  • Secure Text Entry — tryb ukrytego wprowadzania, zastępujący znaki maskującymi symbolami (kropkami) przez PasswordTransformationMethod.
  • Aktywacja — przez inputType="textPassword" lub programowe ustawienie TYPE_TEXT_VARIATION_PASSWORD.
  • PasswordTransformationMethod — wbudowana klasa Androida, zastępująca wyświetlanie znaków bez zmiany Editable.
  • Przełącznik widoczności — realizowany przez TextInputLayout z endIconMode="password_toggle" i TYPE_TEXT_VARIATION_VISIBLE_PASSWORD.
  • Ochrona — zapobiega shoulder surfing, zrzutom ekranu (z FLAG_SECURE), autokorekcie i zapisowi w słowniku.
  • Autofill — dla wsparcia menedżerów haseł dodawaj importantForAutofill i autofillHints="password".
  • Najlepsze praktyki — używaj TextInputLayout, czyść pole przy zwijaniu, nie ograniczaj długości hasła zbyt restrykcyjnie.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również