在 Android 中使用指纹进行身份验证
Android 6.0 (Marshmallow) 附带指纹身份验证,新发布的 API 允许用户使用指纹传感器对智能手机进行身份验证。为了使用指纹传感器对用户进行身份验证,我们需要FingerprintManager类的实例并调用 authenticate() 方法。此外,我们应该注意必须具有指纹传感器的设备。
使用指纹认证的优点:
- 快速、可靠且易于使用
- 高安全性,因为每个人都有独特的指纹
- 最重要的是,无论您的身体或健康状况或无法记住您的密码,指纹始终完美无缺
例子
在这个例子中,我们将构建一个应用程序,要求用户的指纹进行身份验证,如果用户输入了正确的指纹,那么他们就被允许进入应用程序。
分步实施
步骤 1:创建一个新项目
要在 Android Studio 中创建新项目,请参阅如何在 Android Studio 中创建/启动新项目。请注意,选择Java作为编程语言。确保在创建新的 android 项目时将最低 API 级别设置为 23 (Android 6.0) 。
第 2 步:需要许可
为了使用指纹认证,我们需要对我们的AndroidMainfest.xml文件授予USE_FINGERPRINT权限。
XML
XML
#0F9D58
#16E37F
#03DAC5
#000
XML
Java
package com.paulsofts.gfgfingerprintauthentication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Bundle;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.widget.TextView;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
public class MainActivity extends AppCompatActivity {
private KeyStore keyStore;
// Defining variable for storing
// key in android keystore container
private static final String KEY_NAME = "GEEKSFORGEEKS";
private Cipher cipher;
private TextView errorText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initializing KeyguardManager and FingerprintManager
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
// Initializing our error text
errorText = (TextView) findViewById(R.id.errorText);
// Here, we are using various security checks
// Checking device is inbuilt with fingerprint sensor or not
if(!fingerprintManager.isHardwareDetected()){
// Setting error message if device
// doesn't have fingerprint sensor
errorText.setText("Device does not support fingerprint sensor");
}else {
// Checking fingerprint permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
errorText.setText("Fingerprint authentication is not enabled");
}else{
// Check for at least one registered finger
if (!fingerprintManager.hasEnrolledFingerprints()) {
errorText.setText("Register at least one finger");
}else{
// Checking for screen lock security
if (!keyguardManager.isKeyguardSecure()) {
errorText.setText("Screen lock security not enabled");
}else{
// if everything is enabled and correct then we will generate
// the encryption key which will be stored on the device
generateKey();
if (cipherInit()) {
FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
FingerprintHandler helper = new FingerprintHandler(this);
helper.startAuth(fingerprintManager, cryptoObject);
}
}
}
}
}
}
@TargetApi(Build.VERSION_CODES.M)
protected void generateKey() {
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (Exception e) {
e.printStackTrace();
}
KeyGenerator keyGenerator;
try {
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException("KeyGenerator instance failed", e);
}
try {
keyStore.load(null);
keyGenerator.init(new
KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
} catch (NoSuchAlgorithmException |
InvalidAlgorithmParameterException
| CertificateException | IOException e) {
throw new RuntimeException(e);
}
}
@TargetApi(Build.VERSION_CODES.M)
public boolean cipherInit() {
try {
cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException("Cipher failed", e);
}
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Cipher initialization failed", e);
}
}
}
Java
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.CancellationSignal;
import android.widget.TextView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
private Context context;
// Constructor
public FingerprintHandler(Context mContext) {
context = mContext;
}
// Fingerprint authentication starts here..
public void Authentication(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) {
CancellationSignal cancellationSignal = new CancellationSignal();
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
return;
}
manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
}
// On authentication failed
@Override
public void onAuthenticationFailed() {
this.update("Authentication Failed!!!", false);
}
// On successful authentication
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
this.update("Successfully Authenticated...", true);
}
// This method is used to update the text message
// depending on the authentication result
public void update(String e, Boolean success){
TextView textView = (TextView) ((Activity)context).findViewById(R.id.textMsg);
textView.setText(e);
if(success){
textView.setTextColor(ContextCompat.getColor(context,R.color.black));
}
}
}
在进一步移动之前,让我们在colors.xml文件中为我们的应用程序添加一些颜色属性。
XML
#0F9D58
#16E37F
#03DAC5
#000
第 3 步:创建图像资产
在这一步中,我们将为指纹创建一个图像资产。转到drawable>右键单击>新建>矢量资源>剪贴画并搜索指纹并将其添加到drawable文件夹中。
第 4 步:创建指纹布局
现在,我们将为指纹传感器创建布局。转到activity_main.xml并复制以下代码。
XML
第 5 步:使用 MainActivity。Java
在这一步中,我们将介绍我们的 FingerprintManager 类并对其进行初始化。我们将使用generateKey()方法生成一个安全存储在设备上的加密密钥,我们还将使用cipherInit()方法初始化将用于创建加密指纹管理器的密码。下面是MainActivity 的代码。 Java文件。
Java
package com.paulsofts.gfgfingerprintauthentication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Bundle;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.widget.TextView;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
public class MainActivity extends AppCompatActivity {
private KeyStore keyStore;
// Defining variable for storing
// key in android keystore container
private static final String KEY_NAME = "GEEKSFORGEEKS";
private Cipher cipher;
private TextView errorText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initializing KeyguardManager and FingerprintManager
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
// Initializing our error text
errorText = (TextView) findViewById(R.id.errorText);
// Here, we are using various security checks
// Checking device is inbuilt with fingerprint sensor or not
if(!fingerprintManager.isHardwareDetected()){
// Setting error message if device
// doesn't have fingerprint sensor
errorText.setText("Device does not support fingerprint sensor");
}else {
// Checking fingerprint permission
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
errorText.setText("Fingerprint authentication is not enabled");
}else{
// Check for at least one registered finger
if (!fingerprintManager.hasEnrolledFingerprints()) {
errorText.setText("Register at least one finger");
}else{
// Checking for screen lock security
if (!keyguardManager.isKeyguardSecure()) {
errorText.setText("Screen lock security not enabled");
}else{
// if everything is enabled and correct then we will generate
// the encryption key which will be stored on the device
generateKey();
if (cipherInit()) {
FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
FingerprintHandler helper = new FingerprintHandler(this);
helper.startAuth(fingerprintManager, cryptoObject);
}
}
}
}
}
}
@TargetApi(Build.VERSION_CODES.M)
protected void generateKey() {
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (Exception e) {
e.printStackTrace();
}
KeyGenerator keyGenerator;
try {
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException("KeyGenerator instance failed", e);
}
try {
keyStore.load(null);
keyGenerator.init(new
KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
} catch (NoSuchAlgorithmException |
InvalidAlgorithmParameterException
| CertificateException | IOException e) {
throw new RuntimeException(e);
}
}
@TargetApi(Build.VERSION_CODES.M)
public boolean cipherInit() {
try {
cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException("Cipher failed", e);
}
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Cipher initialization failed", e);
}
}
}
第 6 步:创建指纹认证处理程序类
在这一步中,我们将创建一个 FingerprintHandler。 Java类并扩展FingerprintManager.AuthenticationCallback并覆盖方法并提供我们的定义。下面是 FingerpirntHandler 类的代码。
Java
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.CancellationSignal;
import android.widget.TextView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
private Context context;
// Constructor
public FingerprintHandler(Context mContext) {
context = mContext;
}
// Fingerprint authentication starts here..
public void Authentication(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) {
CancellationSignal cancellationSignal = new CancellationSignal();
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
return;
}
manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
}
// On authentication failed
@Override
public void onAuthenticationFailed() {
this.update("Authentication Failed!!!", false);
}
// On successful authentication
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
this.update("Successfully Authenticated...", true);
}
// This method is used to update the text message
// depending on the authentication result
public void update(String e, Boolean success){
TextView textView = (TextView) ((Activity)context).findViewById(R.id.textMsg);
textView.setText(e);
if(success){
textView.setTextColor(ContextCompat.getColor(context,R.color.black));
}
}
}
输出:
我们将在支持指纹传感器的设备上测试我们的应用程序。在这里,首先我们输入了错误的手指,我们得到了 Authentication failed 消息,然后我们将输入正确的手指。