📌  相关文章
📜  在 Android 中使用指纹进行身份验证

📅  最后修改于: 2022-05-13 01:54:35.338000             🧑  作者: Mango

在 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 消息,然后我们将输入正确的手指。