Một phương thức bảo vệ thông tin nhạy cảm hoặc nội dung hàng đầu trong ứng dụng của bạn là yêu cầu xác thực bằng sinh trắc học, chẳng hạn như sử dụng tính năng nhận dạng khuôn mặt hoặc nhận dạng vân tay. Hướng dẫn này giải thích cách hỗ trợ luồng đăng nhập bằng sinh trắc học trong ứng dụng của bạn.
Theo nguyên tắc chung, bạn nên sử dụng Trình quản lý thông tin xác thực để đăng nhập lần đầu trên một thiết bị. Bạn có thể thực hiện các lần uỷ quyền lại sau này bằng Lời nhắc sinh trắc học, hoặc Trình quản lý thông tin xác thực. Ưu điểm của việc sử dụng Lời nhắc về sinh trắc học là công cụ này cung cấp nhiều lựa chọn tuỳ chỉnh hơn, trong khi Trình quản lý thông tin xác thực cung cấp một triển khai trên cả hai quy trình.
Khai báo loại xác thực được ứng dụng của bạn hỗ trợ
Để xác định các loại xác thực được ứng dụng của bạn hỗ trợ, hãy dùng giao diện BiometricManager.Authenticators
. Bạn có thể khai báo các loại xác thực sau:
BIOMETRIC_STRONG
- Xác thực bằng thông tin sinh trắc học Lớp 3, như xác định trên trang định nghĩa về khả năng tương thích với Android..
BIOMETRIC_WEAK
- Xác thực bằng thông tin sinh trắc học Lớp 2, như xác định trên trang định nghĩa về khả năng tương thích với Android..
DEVICE_CREDENTIAL
- Xác thực bằng thông tin xác thực khoá màn hình – mã PIN, hình mở khoá hoặc mật khẩu của người dùng.
Để bắt đầu sử dụng trình xác thực, người dùng cần tạo mã PIN, hình mở khoá hoặc mật khẩu. Nếu người dùng chưa có mã xác thực, thì quy trình đăng ký nhận dạng sinh trắc học sẽ nhắc họ tạo mã.
Để xác định các kiểu xác thực bằng sinh trắc học, được ứng dụng của bạn chấp nhận, hãy chuyển một kiểu xác thực hoặc một tổ hợp bitwise nhiều kiểu xác thực vào phương thức setAllowedAuthenticators()
. Đoạn mã sau đây cho thấy cách hỗ trợ xác thực bằng thông tin sinh trắc học Lớp 3 hoặc thông tin xác thực khoá màn hình.
Kotlin
// Lets the user authenticate using either a Class 3 biometric or // their lock screen credential (PIN, pattern, or password). promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my app") .setSubtitle("Log in using your biometric credential") .setAllowedAuthenticators(BIOMETRIC_STRONG or DEVICE_CREDENTIAL) .build()
Java
// Lets user authenticate using either a Class 3 biometric or // their lock screen credential (PIN, pattern, or password). promptInfo = new BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my app") .setSubtitle("Log in using your biometric credential") .setAllowedAuthenticators(BIOMETRIC_STRONG | DEVICE_CREDENTIAL) .build();
Trên Android 10 (API cấp 29) trở xuống, bạn không thể kết hợp các loại trình xác thực sau: DEVICE_CREDENTIAL
và BIOMETRIC_STRONG | DEVICE_CREDENTIAL
. Để kiểm tra sự hiện diện của mã PIN, hình mở khoá hoặc mật khẩu trên Android 10 trở xuống, hãy sử dụng phương thức KeyguardManager.isDeviceSecure()
.
Kiểm tra xem phương thức xác thực bằng sinh trắc học có trên thiết bị không
Sau khi bạn quyết định chọn phần tử xác thực nào được ứng dụng của bạn hỗ trợ, hãy kiểm tra xem các phần tử này có trên thiết bị không. Để thực hiện việc này, hãy chuyển cùng một kiểu kết hợp bitwise mà bạn đã khai báo bằng phương thức setAllowedAuthenticators()
vào phương thức canAuthenticate()
.
Nếu cần, hãy gọi thao tác theo ý định ACTION_BIOMETRIC_ENROLL
. Trong phần ý định bổ sung, cung cấp tập hợp trình xác thực được ứng dụng của bạn chấp nhận. Ý định này nhắc người dùng đăng ký thông tin xác thực với trình xác thực mà ứng dụng của bạn chấp nhận.
Kotlin
val biometricManager = BiometricManager.from(this) when (biometricManager.canAuthenticate(BIOMETRIC_STRONG or DEVICE_CREDENTIAL)) { BiometricManager.BIOMETRIC_SUCCESS -> Log.d("MY_APP_TAG", "App can authenticate using biometrics.") BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> Log.e("MY_APP_TAG", "No biometric features available on this device.") BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> Log.e("MY_APP_TAG", "Biometric features are currently unavailable.") BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> { // Prompts the user to create credentials that your app accepts. val enrollIntent = Intent(Settings.ACTION_BIOMETRIC_ENROLL).apply { putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, BIOMETRIC_STRONG or DEVICE_CREDENTIAL) } startActivityForResult(enrollIntent, REQUEST_CODE) } }
Java
BiometricManager biometricManager = BiometricManager.from(this); switch (biometricManager.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) { case BiometricManager.BIOMETRIC_SUCCESS: Log.d("MY_APP_TAG", "App can authenticate using biometrics."); break; case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE: Log.e("MY_APP_TAG", "No biometric features available on this device."); break; case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE: Log.e("MY_APP_TAG", "Biometric features are currently unavailable."); break; case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED: // Prompts the user to create credentials that your app accepts. final Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL); enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, BIOMETRIC_STRONG | DEVICE_CREDENTIAL); startActivityForResult(enrollIntent, REQUEST_CODE); break; }
Xác định cách người dùng được xác thực
Sau khi người dùng xác thực, bạn có thể kiểm tra xem người dùng được xác thực bằng thông tin đăng nhập thiết bị hay thông tin xác thực sinh trắc học bằng cách gọi getAuthenticationType()
.
Hiển thị lời nhắc đăng nhập
Để hiển thị lời nhắc của hệ thống đòi hỏi người dùng xác thực bằng thông tin xác thực sinh trắc học, sử dụng Thư viện sinh trắc học. Hộp thoại này (do hệ thống cung cấp) là nhất quán trên các ứng dụng dùng hộp thoại này, tạo ra trải nghiệm người dùng đáng tin cậy hơn. Hộp thoại mẫu được minh hoạ trong hình 1.
Để thêm tính năng xác thực bằng sinh trắc học vào ứng dụng của bạn bằng thư viện Sinh trắc học, hãy hoàn tất các bước sau:
Trong tệp
build.gradle
của mô-đun ứng dụng, thêm phần phụ thuộc vào thư việnandroidx.biometric
.Trong hoạt động hoặc mảnh lưu trữ hộp thoại đăng nhập sinh trắc học, hiển thị hộp thoại sử dụng logic có trong đoạn mã sau:
Kotlin
private lateinit var executor: Executor private lateinit var biometricPrompt: BiometricPrompt private lateinit var promptInfo: BiometricPrompt.PromptInfo override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) executor = ContextCompat.getMainExecutor(this) biometricPrompt = BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) Toast.makeText(applicationContext, "Authentication error: $errString", Toast.LENGTH_SHORT) .show() } override fun onAuthenticationSucceeded( result: BiometricPrompt.AuthenticationResult) { super.onAuthenticationSucceeded(result) Toast.makeText(applicationContext, "Authentication succeeded!", Toast.LENGTH_SHORT) .show() } override fun onAuthenticationFailed() { super.onAuthenticationFailed() Toast.makeText(applicationContext, "Authentication failed", Toast.LENGTH_SHORT) .show() } }) promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my app") .setSubtitle("Log in using your biometric credential") .setNegativeButtonText("Use account password") .build() // Prompt appears when user clicks "Log in". // Consider integrating with the keystore to unlock cryptographic operations, // if needed by your app. val biometricLoginButton = findViewById<Button>(R.id.biometric_login) biometricLoginButton.setOnClickListener { biometricPrompt.authenticate(promptInfo) } }
Java
private Executor executor; private BiometricPrompt biometricPrompt; private BiometricPrompt.PromptInfo promptInfo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); executor = ContextCompat.getMainExecutor(this); biometricPrompt = new BiometricPrompt(MainActivity.this, executor, new BiometricPrompt.AuthenticationCallback() { @Override public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { super.onAuthenticationError(errorCode, errString); Toast.makeText(getApplicationContext(), "Authentication error: " + errString, Toast.LENGTH_SHORT) .show(); } @Override public void onAuthenticationSucceeded( @NonNull BiometricPrompt.AuthenticationResult result) { super.onAuthenticationSucceeded(result); Toast.makeText(getApplicationContext(), "Authentication succeeded!", Toast.LENGTH_SHORT).show(); } @Override public void onAuthenticationFailed() { super.onAuthenticationFailed(); Toast.makeText(getApplicationContext(), "Authentication failed", Toast.LENGTH_SHORT) .show(); } }); promptInfo = new BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my app") .setSubtitle("Log in using your biometric credential") .setNegativeButtonText("Use account password") .build(); // Prompt appears when user clicks "Log in". // Consider integrating with the keystore to unlock cryptographic operations, // if needed by your app. Button biometricLoginButton = findViewById(R.id.biometric_login); biometricLoginButton.setOnClickListener(view -> { biometricPrompt.authenticate(promptInfo); }); }
Sử dụng giải pháp mật mã phụ thuộc vào xác thực
Để tăng cường bảo vệ thông tin nhạy cảm trong ứng dụng của mình, bạn có thể tích hợp tính năng mật mã vào quy trình xác thực bằng sinh trắc học bằng cách sử dụng một thực thể của CryptoObject
.
Khung này hỗ trợ các đối tượng mật mã sau: Signature
, Cipher
và Mac
.
Sau khi người dùng xác thực thành công bằng lời nhắc sinh trắc học, ứng dụng của bạn có thể thực hiện thao tác mã hoá. Ví dụ: nếu xác thực bằng đối tượng Cipher
, thì ứng dụng của bạn có thể thực hiện việc mã hoá và giải mã bằng đối tượng SecretKey
.
Trong các phần sau, bạn sẽ tìm hiểu các ví dụ về sử dụng đối tượng Cipher
và đối tượng SecretKey
để mã hoá dữ liệu. Mỗi ví dụ sử dụng các phương thức sau:
Kotlin
private fun generateSecretKey(keyGenParameterSpec: KeyGenParameterSpec) { val keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init(keyGenParameterSpec) keyGenerator.generateKey() } private fun getSecretKey(): SecretKey { val keyStore = KeyStore.getInstance("AndroidKeyStore") // Before the keystore can be accessed, it must be loaded. keyStore.load(null) return keyStore.getKey(KEY_NAME, null) as SecretKey } private fun getCipher(): Cipher { return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7) }
Java
private void generateSecretKey(KeyGenParameterSpec keyGenParameterSpec) { KeyGenerator keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); keyGenerator.init(keyGenParameterSpec); keyGenerator.generateKey(); } private SecretKey getSecretKey() { KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); // Before the keystore can be accessed, it must be loaded. keyStore.load(null); return ((SecretKey)keyStore.getKey(KEY_NAME, null)); } private Cipher getCipher() { return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7); }
Xác thực chỉ bằng thông tin xác thực sinh trắc học
Nếu ứng dụng của bạn sử dụng khoá bí mật đòi hỏi thông tin xác thực sinh trắc học để mở khoá, thì người dùng phải xác thực thông tin xác thực sinh trắc học của họ mỗi lần ứng dụng truy cập vào khoá.
Để chỉ mã hoá thông tin nhạy cảm sau khi người dùng xác thực bằng thông tin xác nhận sinh trắc học, hãy hoàn tất các bước sau:
Tạo khoá sử dụng cấu hình sau đây
KeyGenParameterSpec
:Kotlin
generateSecretKey(KeyGenParameterSpec.Builder( KEY_NAME, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .setUserAuthenticationRequired(true) // Invalidate the keys if the user has registered a new biometric // credential, such as a new fingerprint. Can call this method only // on Android 7.0 (API level 24) or higher. The variable // "invalidatedByBiometricEnrollment" is true by default. .setInvalidatedByBiometricEnrollment(true) .build())
Java
generateSecretKey(new KeyGenParameterSpec.Builder( KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .setUserAuthenticationRequired(true) // Invalidate the keys if the user has registered a new biometric // credential, such as a new fingerprint. Can call this method only // on Android 7.0 (API level 24) or higher. The variable // "invalidatedByBiometricEnrollment" is true by default. .setInvalidatedByBiometricEnrollment(true) .build());
Bắt đầu một quy trình xác thực bằng sinh trắc học kết hợp một thuật toán mật mã:
Kotlin
biometricLoginButton.setOnClickListener { // Exceptions are unhandled within this snippet. val cipher = getCipher() val secretKey = getSecretKey() cipher.init(Cipher.ENCRYPT_MODE, secretKey) biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher)) }
Java
biometricLoginButton.setOnClickListener(view -> { // Exceptions are unhandled within this snippet. Cipher cipher = getCipher(); SecretKey secretKey = getSecretKey(); cipher.init(Cipher.ENCRYPT_MODE, secretKey); biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher)); });
Bên trong các lệnh gọi lại xác thực bằng sinh trắc học của bạn, hãy sử dụng khoá bí mật để mã hoá thông tin nhạy cảm:
Kotlin
override fun onAuthenticationSucceeded( result: BiometricPrompt.AuthenticationResult) { val encryptedInfo: ByteArray = result.cryptoObject.cipher?.doFinal( // plaintext-string text is whatever data the developer would like // to encrypt. It happens to be plain-text in this example, but it // can be anything plaintext-string.toByteArray(Charset.defaultCharset()) ) Log.d("MY_APP_TAG", "Encrypted information: " + Arrays.toString(encryptedInfo)) }
Java
@Override public void onAuthenticationSucceeded( @NonNull BiometricPrompt.AuthenticationResult result) { // NullPointerException is unhandled; use Objects.requireNonNull(). byte[] encryptedInfo = result.getCryptoObject().getCipher().doFinal( // plaintext-string text is whatever data the developer would like // to encrypt. It happens to be plain-text in this example, but it // can be anything plaintext-string.getBytes(Charset.defaultCharset())); Log.d("MY_APP_TAG", "Encrypted information: " + Arrays.toString(encryptedInfo)); }
Xác thực bằng thông tin xác thực sinh trắc học hoặc thông tin đăng nhập màn hình khoá
Bạn có thể sử dụng khoá bí mật cho phép xác thực bằng thông tin xác thực sinh trắc học hoặc thông tin đăng nhập màn hình khoá (mã PIN, hình mở khoá hoặc mật khẩu). Khi định cấu hình cho khoá này, hãy chỉ định khoảng thời gian hợp lệ. Trong khoảng thời gian này, ứng dụng của bạn có thể thực hiện nhiều thao tác mã hoá mà người dùng không cần xác thực lại.
Để mã hoá thông tin nhạy cảm sau khi người dùng xác thực bằng thông tin xác thực sinh trắc học hoặc thông tin xác thực màn hình khoá, hãy hoàn thành các bước sau:
Tạo khoá sử dụng cấu hình sau đây
KeyGenParameterSpec
:Kotlin
generateSecretKey(KeyGenParameterSpec.Builder( KEY_NAME, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .setUserAuthenticationRequired(true) .setUserAuthenticationParameters(VALIDITY_DURATION_SECONDS, ALLOWED_AUTHENTICATORS) .build())
Java
generateSecretKey(new KeyGenParameterSpec.Builder( KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .setUserAuthenticationRequired(true) .setUserAuthenticationParameters(VALIDITY_DURATION_SECONDS, ALLOWED_AUTHENTICATORS) .build());
Trong khoảng thời gian
VALIDITY_DURATION_SECONDS
sau khi người dùng xác thực, mã hoá thông tin nhạy cảm:Kotlin
private fun encryptSecretInformation() { // Exceptions are unhandled for getCipher() and getSecretKey(). val cipher = getCipher() val secretKey = getSecretKey() try { cipher.init(Cipher.ENCRYPT_MODE, secretKey) val encryptedInfo: ByteArray = cipher.doFinal( // plaintext-string text is whatever data the developer would // like to encrypt. It happens to be plain-text in this example, // but it can be anything plaintext-string.toByteArray(Charset.defaultCharset())) Log.d("MY_APP_TAG", "Encrypted information: " + Arrays.toString(encryptedInfo)) } catch (e: InvalidKeyException) { Log.e("MY_APP_TAG", "Key is invalid.") } catch (e: UserNotAuthenticatedException) { Log.d("MY_APP_TAG", "The key's validity timed out.") biometricPrompt.authenticate(promptInfo) }
Java
private void encryptSecretInformation() { // Exceptions are unhandled for getCipher() and getSecretKey(). Cipher cipher = getCipher(); SecretKey secretKey = getSecretKey(); try { // NullPointerException is unhandled; use Objects.requireNonNull(). ciper.init(Cipher.ENCRYPT_MODE, secretKey); byte[] encryptedInfo = cipher.doFinal( // plaintext-string text is whatever data the developer would // like to encrypt. It happens to be plain-text in this example, // but it can be anything plaintext-string.getBytes(Charset.defaultCharset())); } catch (InvalidKeyException e) { Log.e("MY_APP_TAG", "Key is invalid."); } catch (UserNotAuthenticatedException e) { Log.d("MY_APP_TAG", "The key's validity timed out."); biometricPrompt.authenticate(promptInfo); } }
Xác thực bằng khoá xác thực mỗi lần sử dụng
Bạn có thể hỗ trợ các khoá xác thực cho mỗi lần sử dụng bên trong thực thể của BiometricPrompt
. Một khoá như vậy đòi hỏi người dùng nhập thông tin xác thực sinh trắc học hoặc thông tin đăng nhập thiết bị mỗi khi ứng dụng của bạn cần truy cập dữ liệu do khoá đó bảo vệ. Khoá xác thực cho mỗi lần sử dụng có thể hữu ích cho các giao dịch giá trị cao, chẳng hạn như thanh toán một khoản tiền lớn hoặc cập nhật hồ sơ sức khoẻ của một người.
Để liên kết một đối tượng BiometricPrompt
với khoá xác thực cho mỗi lần sử dụng, thêm mã tương tự vào mẫu sau:
Kotlin
val authPerOpKeyGenParameterSpec = KeyGenParameterSpec.Builder("myKeystoreAlias", key-purpose) // Accept either a biometric credential or a device credential. // To accept only one type of credential, include only that type as the // second argument. .setUserAuthenticationParameters(0 /* duration */, KeyProperties.AUTH_BIOMETRIC_STRONG or KeyProperties.AUTH_DEVICE_CREDENTIAL) .build()
Java
KeyGenParameterSpec authPerOpKeyGenParameterSpec = new KeyGenParameterSpec.Builder("myKeystoreAlias", key-purpose) // Accept either a biometric credential or a device credential. // To accept only one type of credential, include only that type as the // second argument. .setUserAuthenticationParameters(0 /* duration */, KeyProperties.AUTH_BIOMETRIC_STRONG | KeyProperties.AUTH_DEVICE_CREDENTIAL) .build();
Xác thực mà không cần hành động rõ ràng của người dùng
Theo mặc định, hệ thống yêu cầu người dùng thực hiện một hành động cụ thể, chẳng hạn như nhấn một nút, sau khi thông tin xác thực sinh trắc học của người dùng được chấp nhận. Bạn nên ưu tiên dùng cấu hình này nếu ứng dụng của bạn hiển thị hộp thoại để xác nhận một hành động nhạy cảm hoặc có mức độ rủi ro cao, chẳng hạn như mua hàng.
Nếu ứng dụng của bạn hiển thị một hộp thoại xác thực bằng sinh trắc học cho hành động có mức rủi ro thấp hơn, thì bạn có thể gợi ý cho hệ thống rằng người dùng không cần xác nhận xác thực. Gợi ý này có thể cho phép người dùng xem nội dung trong ứng dụng của bạn nhanh hơn sau khi xác thực lại bằng phương thức thụ động, chẳng hạn như nhận dạng khuôn mặt hoặc nhận dạng mống mắt. Để cung cấp gợi ý này, hãy chuyển false
vào phương thức setConfirmationRequired()
.
Hình 2 cho thấy hai phiên bản của cùng một hộp thoại. Một phiên bản yêu cầu hành động rõ ràng của người dùng, phiên bản còn lại thì không.
Đoạn mã sau đây cho thấy cách trình bày một hộp thoại mà không đòi hỏi người dùng phải thực hiện một hành động rõ ràng để hoàn tất quy trình xác thực:
Kotlin
// Lets the user authenticate without performing an action, such as pressing a // button, after their biometric credential is accepted. promptInfo = BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my app") .setSubtitle("Log in using your biometric credential") .setNegativeButtonText("Use account password") .setConfirmationRequired(false) .build()
Java
// Lets the user authenticate without performing an action, such as pressing a // button, after their biometric credential is accepted. promptInfo = new BiometricPrompt.PromptInfo.Builder() .setTitle("Biometric login for my app") .setSubtitle("Log in using your biometric credential") .setNegativeButtonText("Use account password") .setConfirmationRequired(false) .build();
Cho phép dự phòng thông tin xác thực phi sinh trắc học
Nếu muốn ứng dụng của mình cho phép xác thực bằng thông tin nhận dạng sinh trắc học hoặc thông tin xác thực thiết bị, bạn có thể khai báo rằng ứng dụng của bạn hỗ trợ thông tin xác thực thiết bị bằng cách đưa DEVICE_CREDENTIAL
vào tập hợp giá trị mà bạn chuyển vào setAllowedAuthenticators()
.
Nếu ứng dụng của bạn đang sử dụng createConfirmDeviceCredentialIntent()
hoặc setDeviceCredentialAllowed()
để cung cấp tính năng này, hãy chuyển sang sử dụng setAllowedAuthenticators()
.
Tài nguyên khác
Để tìm hiểu thêm về tính năng xác thực bằng sinh trắc học trên Android, hãy tham khảo các tài nguyên sau.