我在android设备中自定义biometricPrompt遇到问题。我仅使用带有指纹的授权,但是如果允许使用android 9.0的某些设备(例如Samsung Galaxy S10 +)进行授权,则使用指纹,但与面部认证相同。如果用户同时允许面部和指纹身份验证生物识别,则提示使用该身份验证来进行面部识别。我需要只允许指纹,如果用户不允许指纹,但是面部允许,我需要阻止它。
文档告诉我了这一点(来自docs)
...但是没有任何方向,我在源代码中找不到有关自定义的任何内容。
我用于启动身份验证对话框的代码在这里
databaseReference.child(firebaseAuth.getUid()).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
RequestEntries requestEntries = dataSnapshot.getValue(RequestEntries.class);
requestfirstname.setText(requestEntries.getRequestFirstName() + " " + requestEntries.getRequestLastName());
requestcontactnumber.setText(requestEntries.getRequestContactNumber());
requestlocation.setText(requestEntries.getRequestLocation());
requestlandmarks.setText(requestEntries.getRequestLandmarks());
感谢您的帮助
答案 0 :(得分:1)
有点晚了,但是我希望这个答案可以对其他开发人员有所帮助。 我还试图实现相同的目标,并最终得到了一个简单的解决方案:
像这样调用.authenticate()
时提供一个加密对象:
/**
* Prerequisites:
* 1. Add
* `implementation "androidx.biometric:biometric:1.0.1"` in build.gradle
* 2. Add
* ` <uses-permission android:name="android.permission.USE_BIOMETRIC" android:requiredFeature="false"/>`
* in AndroidManifest.xml
*/
object BiometricHelper {
private const val ENCRYPTION_BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM
private const val ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_NONE
private const val ENCRYPTION_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES
private const val KEY_SIZE = 128
private lateinit var biometricPrompt: BiometricPrompt
fun authenticate(fragmentActivity: FragmentActivity, authCallback: BiometricPrompt.AuthenticationCallback){
try {
if (!fragmentActivity.supportFragmentManager.executePendingTransactions()) {
biometricPrompt = createBiometricPrompt(fragmentActivity, authCallback)
val promptInfo = createPromptInfo()
biometricPrompt.authenticate(
promptInfo,
cryptoObject //Providing crypto object here will block Iris and Face Scan
)
}
}
catch (e: KeyPermanentlyInvalidatedException) {
e.printStackTrace()
}
catch (e: Exception) {
e.printStackTrace()
}
}
private fun createBiometricPrompt(fragmentActivity: FragmentActivity, authCallback: BiometricPrompt.AuthenticationCallback): BiometricPrompt {
val executor = ContextCompat.getMainExecutor(fragmentActivity)
return BiometricPrompt(fragmentActivity, executor, authCallback)
}
private fun createPromptInfo(): BiometricPrompt.PromptInfo {
return BiometricPrompt.PromptInfo.Builder()
.setTitle("Authentication")
.setConfirmationRequired(false)
.setNegativeButtonText("Cancel")
.setDeviceCredentialAllowed(false) //Don't Allow PIN/pattern/password authentication.
.build()
}
//endregion
//====================================================================================
//region Dummy crypto object that is used just to block Face, Iris scan
//====================================================================================
/**
* Crypto object requires STRONG biometric methods, and currently Android considers only
* FingerPrint auth is STRONG enough. Therefore, providing a crypto object while calling
* [androidx.biometric.BiometricPrompt.authenticate] will block Face and Iris Scan methods
*/
private val cryptoObject by lazy {
getDummyCryptoObject()
}
private fun getDummyCryptoObject(): BiometricPrompt.CryptoObject {
val transformation = "$ENCRYPTION_ALGORITHM/$ENCRYPTION_BLOCK_MODE/$ENCRYPTION_PADDING"
val cipher = Cipher.getInstance(transformation)
var secKey = getOrCreateSecretKey(false)
try {
cipher.init(Cipher.ENCRYPT_MODE, secKey)
}
catch (e: KeyPermanentlyInvalidatedException) {
e.printStackTrace()
secKey = getOrCreateSecretKey(true)
cipher.init(Cipher.ENCRYPT_MODE, secKey)
}
catch (e: Exception) {
e.printStackTrace()
}
return BiometricPrompt.CryptoObject(cipher)
}
private fun getOrCreateSecretKey(mustCreateNew: Boolean): SecretKey {
val keyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(null)
if (!mustCreateNew) {
keyStore.getKey("dummyKey", null)?.let { return it as SecretKey }
}
val paramsBuilder = KeyGenParameterSpec.Builder("dummyKey",
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
paramsBuilder.apply {
setBlockModes(ENCRYPTION_BLOCK_MODE)
setEncryptionPaddings(ENCRYPTION_PADDING)
setKeySize(KEY_SIZE)
setUserAuthenticationRequired(true)
}
val keyGenParams = paramsBuilder.build()
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore")
keyGenerator.init(keyGenParams)
return keyGenerator.generateKey()
}
//endregion
}
编辑: 仅当该设备上的面部扫描和/或虹膜扫描身份验证被视为弱方法时,此解决方案才有效。