在 Android 中使用指纹进行身份验证
您必须手动输入用户名和密码才能登录某些 Android 应用程序的日子已经一去不复返了。不仅您必须手动输入,而且这也是一个耗时的过程。此外,如果您忘记了密码或用户名,则必须通过一系列步骤来恢复它。但另一方面,如果我们使用指纹进行身份验证,则无需记住密码。此外,没有两个人可以拥有相同的指纹,所以我们不必担心真实性。
因此,在这篇文章中,我们将学习如何在我们的 Android 应用程序中使用指纹认证。那么,让我们开始吧。
指纹认证概述
随着 Android 6.0 (Android M) 的发布,API 发生了大量变化,其中之一就是指纹认证。现在,我们可以在具有指纹传感器的设备中轻松地在我们的应用程序中实现指纹认证。指纹认证的整个过程可以概括为以下几个步骤:
- 在项目的清单文件中请求指纹认证权限。
- 由于指纹只能在其锁屏受 PIN、图案或密码保护的设备上注册。因此,我们必须检查设备的锁定屏幕是否受 PIN、图案或密码保护。
- 然后,创建 FingerprintManager 类的实例。
- 您必须访问用于在 Android 设备上存储加密密钥的存储区域,即 Keystore。因此,创建一个 Keystore 实例以获取对 Android Keystore 容器的访问权限。之后,借助 keyGenerator 类生成加密密钥并将其存储在 Keystore 容器中。
- 借助生成并存储在 Keystore 容器中的密钥,初始化 Cipher 类的实例,并使用该实例创建一个 CryptoObject 并将其分配给您之前创建的 FringerprintManager 实例。
- 调用 FingerprintManger 类的 authenticate 方法并实现处理回调的方法。
指纹认证实现
所以,我们已经看到了指纹认证的理论。现在让我们继续执行相同的部分。
在 Android Studio 中创建一个新项目并根据您的选择命名。此外,将最低 API 设置为 23,即 Android 6.0。
创建项目后,请确保您的设备具有指纹以外的某种身份验证,因为指纹身份验证仅在这种情况下有效。
在你的androidmanifest.xml文件中添加指纹的权限。因此,在清单文件中添加 USE_FINGERPRINT 权限:
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
在进入应用程序的编码部分之前,让我们为 UI 部分编写代码。在 UI 中,我们将拥有一个 ImageView 和一个 TextView。因此,activity_main.xml文件的代码是:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ImageViewandroid:layout_width="160dp"android:layout_height="160dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"android:layout_marginStart="8dp"app:layout_constraintBottom_toBottomOf="parent"android:layout_marginTop="8dp"app:layout_constraintTop_toTopOf="parent"android:layout_marginBottom="8dp"android:src="@drawable/ic_fingerprint"android:layout_marginEnd="8dp"android:id="@+id/fingerprint_iv"/><TextViewandroid:id="@+id/fingerprint_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"android:layout_marginTop="32dp"app:layout_constraintTop_toBottomOf="@+id/fingerprint_iv"android:layout_marginEnd="8dp"android:text="Touch the Fingerpeint Sensor"android:textSize="24sp"/></androidx.constraintlayout.widget.ConstraintLayout>
您可以根据自己的选择替换 ImageView 的图像。
指纹认证使用 KeyguardManager 和 FingerprintManager。所以,在 onCreate() 函数中,需要获取这两个服务:
class MainActivity : AppCompatActivity() {private lateinit var fingerprintManager: FingerprintManagerprivate lateinit var keyguardManager: KeyguardManageroverride fun onCreate(savedInstanceState: Bundle) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)if (checkLockScreen()) {//some other task}}private fun checkLockScreen(): Boolean {keyguardManager = getSystemService(Context.KEYGUARD_SERVICE)as KeyguardManagerfingerprintManager = getSystemService(Context.FINGERPRINT_SERVICE)as FingerprintManager//some other task}
}
我们的下一个任务是检查锁定屏幕是否受 PIN 或密码保护。此外,如果它受密码保护,那么我们会检查某些指纹是否已经与设备相关联。因此,我们将在MainActivity.kt文件的**checkLockScreen()**方法中执行这些检查。
private fun checkLockScreen(): Boolean {keyguardManager = getSystemService(Context.KEYGUARD_SERVICE)as KeyguardManagerfingerprintManager = getSystemService(Context.FINGERPRINT_SERVICE)as FingerprintManagerif (keyguardManager.isKeyguardSecure == false) {Toast.makeText(this,"Lock screen security not enabled",Toast.LENGTH_LONG).show()return false}if (ActivityCompat.checkSelfPermission(this,Manifest.permission.USE_FINGERPRINT) !=PackageManager.PERMISSION_GRANTED) {Toast.makeText(this,"Permission not enabled (Fingerprint)",Toast.LENGTH_LONG).show()return false}if (fingerprintManager.hasEnrolledFingerprints() == false) {Toast.makeText(this,"No fingerprint registered, please register",Toast.LENGTH_LONG).show()return false}return true
}
现在,我们必须生成一个加密密钥,该密钥将存储在 Android 密钥库系统中。因此,我们必须获得 Keystore 的访问权限,然后在generateKey()方法的帮助下生成加密密钥。
class MainActivity : AppCompatActivity() {...private lateinit var keyStore: KeyStoreprivate lateinit var keyGenerator: KeyGeneratorprivate val KEY_NAME = "my_key"...override fun onCreate(savedInstanceState: Bundle) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)if (checkLockScreen()) {generateKey()//some code}}private fun checkLockScreen(): Boolean {//some code}private fun generateKey() {try {keyStore = KeyStore.getInstance("AndroidKeyStore")} catch (e: Exception) {e.printStackTrace()}try {keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES,"AndroidKeyStore")} catch (e: NoSuchAlgorithmException) {throw RuntimeException("Failed to get KeyGenerator instance", e)} catch (e: NoSuchProviderException) {throw RuntimeException("Failed to get KeyGenerator instance", e)}try {keyStore.load(null)keyGenerator.init(KeyGenParameterSpec.Builder(KEY_NAME,KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT).setBlockModes(KeyProperties.BLOCK_MODE_CBC).setUserAuthenticationRequired(true).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7).build())keyGenerator.generateKey()} catch (e: NoSuchAlgorithmException) {throw RuntimeException(e)} catch (e: InvalidAlgorithmParameterException) {throw RuntimeException(e)} catch (e: CertificateException) {throw RuntimeException(e)} catch (e: IOException) {throw RuntimeException(e)}}
}
所以,到目前为止,我们已经生成了密钥。我们的下一个任务是初始化将用于 CryptoObject 实例的密码。此 CryptoObject 将在指纹认证过程中使用。因此,在MainActivity.kt文件中创建一个名为initCipher()的方法:
class MainActivity : AppCompatActivity() {...private lateinit var cipher: Cipherprivate lateinit var cryptoObject: FingerprintManager.CryptoObjectoverride fun onCreate(savedInstanceState: Bundle) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)if (checkLockScreen()) {generateKey()if (initCipher()) {cipher.let {cryptoObject = FingerprintManager.CryptoObject(it)}}}}private fun checkLockScreen(): Boolean {//some code}private fun generateKey() {//some code}private fun initCipher(): Boolean {try {cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"+ KeyProperties.BLOCK_MODE_CBC + "/"+ KeyProperties.ENCRYPTION_PADDING_PKCS7)} catch (e: NoSuchAlgorithmException) {throw RuntimeException("Failed to get Cipher", e)} catch (e: NoSuchPaddingException) {throw RuntimeException("Failed to get Cipher", e)}try {keyStore.load(null)val key = keyStore.getKey(KEY_NAME, null) as SecretKeycipher.init(Cipher.ENCRYPT_MODE, key)return true} catch (e: KeyPermanentlyInvalidatedException) {return false} catch (e: KeyStoreException) {throw RuntimeException("Failed to init Cipher", e)} catch (e: CertificateException) {throw RuntimeException("Failed to init Cipher", e)} catch (e: UnrecoverableKeyException) {throw RuntimeException("Failed to init Cipher", e)} catch (e: IOException) {throw RuntimeException("Failed to init Cipher", e)} catch (e: NoSuchAlgorithmException) {throw RuntimeException("Failed to init Cipher", e)} catch (e: InvalidKeyException) {throw RuntimeException("Failed to init Cipher", e)}}
}
因此,我们完成了密钥生成、密码和密码对象。每当我们需要指纹认证时,就会调用 FingerprintManager 的authenticate方法,因此,可能会根据认证的失败或成功发生一些事件。因此,这些回调事件和身份验证方法必须在扩展 FingerprintManager.AuthenticationCallback 的类中实现。在您的项目中,添加一个名为FingerprintHelper.kt的类并添加以下代码行:
@SuppressLint("ByteOrderMark")
class FingerprintHelper(private val appContext: Context) : FingerprintManager.AuthenticationCallback() {lateinit var cancellationSignal: CancellationSignalfun startAuth(manager: FingerprintManager,cryptoObject: FingerprintManager.CryptoObject) {cancellationSignal = CancellationSignal()if (ActivityCompat.checkSelfPermission(appContext,Manifest.permission.USE_FINGERPRINT) !=PackageManager.PERMISSION_GRANTED) {return}manager.authenticate(cryptoObject, cancellationSignal, 0, this, null)}override fun onAuthenticationError(errMsgId: Int,errString: CharSequence) {Toast.makeText(appContext,"Authentication error\n" + errString,Toast.LENGTH_LONG).show()}override fun onAuthenticationHelp(helpMsgId: Int,helpString: CharSequence) {Toast.makeText(appContext,"Authentication help\n" + helpString,Toast.LENGTH_LONG).show()}override fun onAuthenticationFailed() {Toast.makeText(appContext,"Authentication failed.",Toast.LENGTH_LONG).show()}override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult) {Toast.makeText(appContext,"Authentication succeeded.",Toast.LENGTH_LONG).show()}
}
现在,最后在 MainActivity 的 onCreate 方法中,我们必须创建 FingerprintHelper 类的新实例来启动startAuth方法。
override fun onCreate(savedInstanceState: Bundle) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)if (checkLockScreen()) {generateKey()if (initCipher()) {cipher.let {cryptoObject = FingerprintManager.CryptoObject(it)}val helper = FingerprintHelper(this)if (fingerprintManager != null && cryptoObject != null) {helper.startAuth(fingerprintManager, cryptoObject)}}}
}
最后
在具有指纹传感器的设备上运行应用程序。另外,尝试不同的情况。例如,删除与您的设备关联的所有指纹,删除您设备的密码。
在 Android 中使用指纹进行身份验证相关推荐
- 如何使用Google Authenticator在ASP.NET Core中设置两因素身份验证
介绍 (Introduction) In this article, we are going to learn how to perform two-factor authentication in ...
- ASP.NET的MVC中使用Cookie做身份验证(附代码下载)
场景 ASP.NET的MVC中使用Session做身份验证(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1071 ...
- 如何使用Java和XML Config在Spring Security中启用HTTP基本身份验证
在上一篇文章中,我向您展示了如何在Java应用程序中启用Spring安全性 ,今天我们将讨论如何使用Spring Security 在Java Web应用程序中启用Basic HTTP身份验证 . 如 ...
- 在SPA应用中利用JWT进行身份验证
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载. https://blog.csdn.net/chszs/article/details/79639919 在SPA应用中利用JWT进行 ...
- aws rds监控慢sql_AWS RDS SQL Server中的初始Windows身份验证配置
aws rds监控慢sql In this article, we will be exploring the process of enabling Windows authentication i ...
- aws rds监控慢sql_AWS RDS SQL Server中的高级Windows身份验证配置
aws rds监控慢sql This article will cover advanced configurations for Windows Authentication in AWS RDS ...
- C#中连接使用Windows身份验证的sql server数据库
C#中连接使用Windows身份验证的sql server数据库 最近在写一个系统,主要使用C#语言完成系统内各功能模块的编写.系统包含数据库,需要对数据库内的数据进行增删改查,这就涉及到了数据库的连 ...
- Android 显示 指纹/人脸 身份验证对话框
1. 前言 为了增加用户的隐私和安全,需保护您的应用中的敏感信息或付费内容,一种方法是请求生物识别身份验证,例如使用人脸识别或指纹识别.本篇文章介绍了如何在您的应用中支持生物识别登录流程. 2. 声明 ...
- ASP.NET的MVC中使用Session做身份验证(附代码下载)
场景 ASP.NET中MVC编程模式简介与搭建HelloWorld项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10679 ...
- android10热点验证身份,在 Android 上使用 Microsoft 进行身份验证
使用 OAuth 提供方对象进行 Firebase 身份验证.请注意,与其他 FirebaseAuth 操作不同,此操作会弹出自定义 Chrome 标签页,从而控制您的界面.因此,请不要在您附加的 O ...
最新文章
- ie和firefox操作table对象的异同
- TYVJ P1053 字符串的展开 Label:字符 水
- 区块链BaaS云服务(17)纸贵科技DID分布式身份标识
- 剑指Kubernetes 揭秘腾讯云的PaaS技术选型策略
- 关于flock文件锁的阻塞与非阻塞
- elasticsearch rest api操作
- php 赋值 递增,PHP 基础(赋值及函数)
- fedora如何隐藏顶部状态栏_藏在 iOS 13 里的 9 个隐藏小技巧
- [003]容器和动态数组的使用
- 用aspnet_compiler发布网站 (转载:My way of my life )
- 将本地SQL Server数据库迁移到Azure SQL数据库
- Wireshark实战分析之ICMP协议(二)
- Skyline软件系列平台
- 计算机实验室建设论证报告,计算机实验室实习报告-报告.doc
- creator多点触摸理解
- HTML自动填充表格,word文档中如何实现表格自动填充
- 严格执行系统,严格止损,不要心存侥幸,勇敢承认错误,不给自己的错误找理由。
- PTA-链表学习-----奇数值结点链表
- java学习笔记20(Lambda表达式、函数式编程、流式计算、练习)
- el-upload 模拟点击
热门文章
- matlab绘制蜗牛圈圈图,Matlab实现的图像中的圆、矩形、正方形等形状识别
- 计算机程序无法响应如何解决,电脑卡死出现应用程序未响应不可以正常工作怎么办?...
- ADS2015导入飞思卡尔元器件模型 安装DesignKit
- 详细跨境电商模式分析
- win10重置系统后右键一直转圈,解决鼠标右键一直转圈问题
- 负载均衡(Load Balance)
- 20162328WJH实验五网络编程与安全实验报告
- linux加密自己的smb目录,SmbFile连接加密共享文件夹
- 个性化网站建设的一般流程
- 计算机硬件系统包括哪几部分组成,计算机硬件系统由哪几部分组成