iOS Touch ID(指纹识别)基本开发实践

自 iPhone 5S 开始始,苹果公司推出了全新生物安全识别技术 — 指纹识别验证(Touch ID),苹果把用户的指纹数据存放在处理器的安全区域(Secure Enclave)中,并且提供 Touch ID 给第三方应用程序使用,程序只会收到认证是否成功的通知,而无法访问 Touch ID 或与已注册指纹相关的数据,所以很多银行类、支付类 APP 都集成了指纹、手势等二次验证功能,今天这篇文章就谈谈 Touch ID 开发的基本使用和注意

1.指纹识别的基本知识

指纹识别的功能的使用需要引入 LocalAuthentication 这个框架,这个框架里有三个主要的类:

  • LAContext
  • LAError
  • LAPublicDefines

1.1 LAPublicDefines

从简单的开始,从这个类的命名就知道它的作用了,这是一个公共宏定义类,里面包含了许多定义好的宏,这些宏会在 LAContext 使用到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Policies
public var kLAPolicyDeviceOwnerAuthenticationWithBiometrics: Int32 { get }
public var kLAPolicyDeviceOwnerAuthentication: Int32 { get }
// Options
public var kLAOptionUserFallback: Int32 { get }
public var kLAOptionAuthenticationReason: Int32 { get }
// Credential types
public var kLACredentialTypePasscode: Int32 { get }
public var kLACredentialTypePassphrase: Int32 { get }
public var kLACredentialCTKPIN: Int32 { get }
// Error codes
public var kLAErrorAuthenticationFailed: Int32 { get }
public var kLAErrorUserCancel: Int32 { get }
public var kLAErrorUserFallback: Int32 { get }
public var kLAErrorSystemCancel: Int32 { get }
public var kLAErrorPasscodeNotSet: Int32 { get }
public var kLAErrorTouchIDNotAvailable: Int32 { get }
public var kLAErrorTouchIDNotEnrolled: Int32 { get }
public var kLAErrorTouchIDLockout: Int32 { get }
public var kLAErrorAppCancel: Int32 { get }
public var kLAErrorInvalidContext: Int32 { get }
// Error domain
public var kLAErrorDomain: String { get }

1.2 LAError

这个类其实也不用赘述,就是一个枚举,里面写的是错误的类型,其实就是把上面的 kLAError 宏写进这个枚举了,具体代码注释写的很清晰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/// Authentication was not successful, because user failed to provide valid credentials.
case authenticationFailed
/// Authentication was canceled by user (e.g. tapped Cancel button).
case userCancel
/// Authentication was canceled, because the user tapped the fallback button (Enter Password).
case userFallback
/// Authentication was canceled by system (e.g. another application went to foreground).
case systemCancel
/// Authentication could not start, because passcode is not set on the device.
case passcodeNotSet
/// Authentication could not start, because Touch ID is not available on the device.
case touchIDNotAvailable
/// Authentication could not start, because Touch ID has no enrolled fingers.
case touchIDNotEnrolled
/// Authentication was not successful, because there were too many failed Touch ID attempts and
/// Touch ID is now locked. Passcode is required to unlock Touch ID, e.g. evaluating
/// LAPolicyDeviceOwnerAuthenticationWithBiometrics will ask for passcode as a prerequisite.
@available(iOS 9.0, *)
case touchIDLockout
/// Authentication was canceled by application (e.g. invalidate was called while
/// authentication was in progress).
@available(iOS 9.0, *)
case appCancel
/// LAContext passed to this call has been previously invalidated.
@available(iOS 9.0, *)
case invalidContext

1.2 LAContext

LAContext 用来创建一个管理认证的上下文, LAContext 类提供了用于评估身份验证策略、访问控制、管理凭据以及认证上下文是否有效的接口,LAContext 提供了以下两个主要的方法:

1
2
3
4
5
//判断运行的设备是否支持Touch ID
func canEvaluatePolicy(_ policy: LAPolicy, error: NSErrorPointer) -> Bool
//来验证识别的情况
func evaluatePolicy(_ policy: LAPolicy, localizedReason: String, reply: @escaping (Bool, Error?) -> Swift.Void)

evaluatePolicy 验证指纹的方法里面需要传入一个 policy 参数用来指定指纹验证的模式,这个参数的类型 LAPolicy 是一个枚举:

1
2
3
4
5
6
7
8
9
public enum LAPolicy : Int {
/// Device owner was authenticated using a biometric method (Touch ID).
@available(iOS 8.0, *)
case deviceOwnerAuthenticationWithBiometrics
/// Device owner was authenticated by Touch ID or device passcode.
@available(iOS 9.0, *)
case deviceOwnerAuthentication
}

deviceOwnerAuthenticationWithBiometrics 表示用指纹识别 iOS 8 可用

deviceOwnerAuthentication 表示用指纹或者密码识别,iOS 9 可用

App 中集成指纹识别是跟系统解锁 iPhone 用的一套指纹识别,就是说假如在 App 中指纹识别错误了5次(iOS 系统默认指纹识别错误5次后,指纹识别会被判定为无效状态),那么不仅 App 中的指纹识别系统是无效的,系统的 iPhone 指纹识别解锁系统也是无效的,必须输入 iPhone 解锁密码验证之后,指纹识别才会被系统重新判别为有效

2.指纹识别的基本使用

使用指纹识别比较简单,看示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
func fingerprintRecognition(_ sender: UIButton) {
let context = LAContext()
//用于设置提示语,表示为什么要使用Touch ID
let localizedSting = "demo test"
//这个属性是修改指纹验证失败之后的输入密码按钮标题,传 "" 按钮则不显示,iOS 9 之后可用
context.localizedFallbackTitle = "验证登录密码"
//这个属性是修改指纹验证时取消按钮的标题 iOS 10 之后可用
context.localizedCancelTitle = "不验证了"
var authError:NSError? = nil
if context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error:&authError){
context.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: localizedSting, reply: { (success, error) in // 这个是用来验证TouchID的,会有弹出框出来
if (success) {
print("指纹识别成功")
DispatchQueue.main.async {
//验证成功,主线程处理UI
}
} else {
print("指纹识别失败\(String(describing: error?.localizedDescription))")
if let errorCode = LAError.Code(rawValue: (error! as NSError).code) {
switch errorCode {
case .systemCancel:
print("系统取消授权,如其他APP切入")
case .userCancel:
print("用户取消验证Touch ID")
case .authenticationFailed:
print("授权失败")
case.passcodeNotSet:
print("系统未设置密码")
case .touchIDNotAvailable:
print("设备Touch ID不可用,例如未打开")
case.touchIDNotEnrolled:
print("设备Touch ID不可用,用户未录入")
case .userFallback:
DispatchQueue.main.async {
print("用户指纹错误,切换主线程处理")
}
default: break
}
}
}
})
}else {
print("不支持touchid \(authError)")
if let errorCode = LAError.Code(rawValue: (authError?.code)!) {
switch errorCode {
case .touchIDNotEnrolled:
print("TouchID is not enrolled")
case .passcodeNotSet:
print("A passcode has not been set")
default:break
}
}
}
}

localizedFallbackTitlelocalizedCancelTitlelocalizedReason 的设置分别对应下面图示,需要注意他们对应使用 iOS 版本

3.指纹识别两种模式注意

从上面的学习内容可以看出使用指纹识别有一点需要特别注意:那就是要区分 iOS 系统的版本然后选用不同的 API,因为现在的公司项目至少要从 iOS 8 兼容起,而指纹识别里面的 API 正好全部分散在 iOS 8、9、10 三个系统版本里面,而 deviceOwnerAuthenticationWithBiometricsdeviceOwnerAuthentication 这两个验证模式在不同 iOS 版本中的响应方式也有所不同,因为我没有iOS 8、9 的iPhone 测试这两种方式的不同,推荐看下面这篇文章,文章详细的说明了这两种模式在 iOS 不同版本的系统里表现的不同之处,有条件可以自己按照文章测试一下:

iOS 指纹识别在不同的 iOS 版本中响应方式

其他相关文章:
iOS 指纹识别常见问题汇总

iOS指纹识别登录流程及实现

本人刚开始写博客,主要是为了给自己的知识点做一个笔记,方便自己以后查阅,如果能让别人有所启发也是荣幸之至!如有错误,欢迎指正!