簡述: 在類似支付寶為首的應用以及各種理財等涉及錢財對安全性要求較高的應用中,目前普遍對關鍵數據都做了安全訪問限制,比如通過手勢密碼、指紋密碼等手段,本章主要分析一下iOS開發中指紋識別的一些坑和技術要點。
指紋識別
指紋識別是iPhone5s iOS8.0之后推出的功能,需要硬件以及軟件的支持。指紋識別的功能定義在系統框架<LocalAuthentication/LocalAuthentication.h>
中,并且在app中集成指紋識別是跟系統解鎖iPhone用的一套指紋識別,就是說假如在app中指紋識別錯誤了5次(iOS 系統默認指紋識別錯誤5次后,指紋識別會被判定為無效狀態),那么不僅app中的指紋識別系統是無效的,系統的iPhone指紋識別解鎖系統也是無效的,必須輸入iPhone解鎖口令碼驗證之后,指紋識別才會被系統重新判別為有效!指紋識別有兩個模式:
typedef NS_ENUM(NSInteger, LAPolicy)
{
//8.0支持的API
LAPolicyDeviceOwnerAuthenticationWithBiometrics NS_ENUM_AVAILABLE(NA, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0) = kLAPolicyDeviceOwnerAuthenticationWithBiometrics,
//9.0支持的API
LAPolicyDeviceOwnerAuthentication NS_ENUM_AVAILABLE(10_11, 9_0) = kLAPolicyDeviceOwnerAuthentication
} NS_ENUM_AVAILABLE(10_10, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0);
需要注意的是開發的時候一定要注意區分iOS系統的版本選用不同的API,避免出現重大問題。同時這兩個不同的模式的響應方式也是不同的:
LAPolicyDeviceOwnerAuthenticationWithBiometrics
生物指紋識別。驗證彈框有兩個按鈕,第一個是取消按鈕,第二個按鈕可以自定義標題名稱(默認是"輸入密碼")。只有在第一次指紋驗證失敗后才會出現第二個按鈕,這種鑒定方式的第二個按鈕的功能自定義,第二個按鈕的功能不做處理的話不會有任何響應。
前三次指紋驗證失敗,指紋驗證框不再彈出。再次重新進入驗證,還有兩次驗證機會,如果還是驗證失敗,TOUCH ID 被鎖住不再繼續彈出指紋驗證框。(在iOS10.0以下系統中,不包括iOS 10.0,以后每次進來驗證都是調用系統的設備密碼直至輸入正確的設備密碼方可解除TOUCH ID鎖,但是在iOS 10.0系統中,指紋識別累計錯誤5次系統判定指紋無效后不會彈出系統的設備密碼輸入頁面,尷尬......開發的時候誰曉得iOS 10有這個大坑,被坑慘了。
Talk is cheap,show me the code.
- (void)checkTouchID{
LAContext *laContext = [[LAContext alloc] init];
//去掉 “輸入密碼”,這行代碼可以去掉“輸入密碼”的按鈕
laContext.localizedFallbackTitle = @"";
NSError *error;
if ([laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
NSLog(@"指紋識別有效");
[laContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:@"通過Home鍵驗證已有手機指紋"
reply:^(BOOL success, NSError *error) {
if (success) {
//指紋驗證通過
}else if (error.code == kLAErrorUserCancel){
//用戶點擊取消
}else if (error.code == kLAErrorAuthenticationFailed){
//用戶驗證沒有通過,指紋錯誤
}
}];
}else {
NSLog(@"指紋識別無效%@",error.localizedDescription);
//不支持指紋識別,LOG出錯誤詳情
switch (error.code) {
case LAErrorTouchIDNotEnrolled:
{
NSLog(@"TouchID is not enrolled");
break;
}
case LAErrorPasscodeNotSet:
{
NSLog(@"A passcode has not been set");
break;
}
default:
{
NSLog(@"TouchID not available");
break;
}
}
}
}
在iOS10系統中,指紋識別錯誤5次后,調用[laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]
就會返回NO,在- (void)checkTouchID
方法中,就會打印信息:NSLog(@"指紋識別無效%@",error.localizedDescription);
代碼會跳到這個位置。
在iOS9、iOS8 系統中,指紋識別錯誤5次后,調用[laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]
就會返回YES,在- (void)checkTouchID
方法中,就會打印信息:指紋識別有效。 代碼會跳到這個位置。NSLog(@"指紋識別有效");
LAPolicyDeviceOwnerAuthentication
生物指紋識別或系統密碼驗證。注意這個policy是9.0的API,對于8.0系統的手機不能使用。如果TOUCH ID 可用,且已經錄入指紋,則優先調用指紋驗證。其次是調用系統密碼驗證,如果沒有開啟設備密碼,則不可以使用這種驗證方式。指紋識別驗證失敗三次將自動彈出設備密碼輸入框,如果不進行密碼輸入。再次進來還可以有兩次機會驗證指紋,如果都失敗則TOUCH ID被鎖住。以后也只能彈出設備密碼輸入框。補充:值得注意的是在iOS9系統中,前三次驗證失敗會自動彈出密碼驗證框,后兩次驗證失敗后不會自動彈出密碼驗證框。而在iOS 10系統中,前三次驗證失敗或者后兩次驗證失敗,都會自動彈出密碼驗證框。
- (void)checkTouchID{
LAContext *laContext = [[LAContext alloc] init];
//去掉 “輸入密碼”
laContext.localizedFallbackTitle = @"";
NSError *error;
if ([laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error]) {
NSLog(@"指紋識別有效");
[laContext evaluatePolicy:LAPolicyDeviceOwnerAuthentication
localizedReason:@"通過Home鍵驗證已有手機指紋"
reply:^(BOOL success, NSError *error) {
if (success) {
//指紋驗證通過
}else if (error.code == kLAErrorUserCancel){
//用戶點擊取消
}else if (error.code == kLAErrorAuthenticationFailed){
//用戶驗證沒有通過,指紋錯誤
}
}];
}else {
NSLog(@"指紋識別無效%@",error.localizedDescription);
//不支持指紋識別,LOG出錯誤詳情
switch (error.code) {
case LAErrorTouchIDNotEnrolled:
{
NSLog(@"TouchID is not enrolled");
break;
}
case LAErrorPasscodeNotSet:
{
NSLog(@"A passcode has not been set");
break;
}
default:
{
NSLog(@"TouchID not available");
break;
}
}
}
}
在iOS9、iOS 10系統中,這個policy默認也有兩個按鈕,第一次驗證指紋識別后會顯示兩個按鈕,第二個按鈕是"輸入密碼",默認點擊第二個按鈕會彈出設備密碼輸入框。
異常情況
上面所描述的是iOS系統設置了口令密碼,同時也添加了指紋的情況。但是用戶在使用過程中可能會出現各種情況,下面分析一下兩種policy在不同系統上,只有口令密碼、只有指紋、沒有口令也沒有指紋的情況下所作出的響應,通過打印輸出結果確定代碼的跳轉位置。
LAPolicyDeviceOwnerAuthenticationWithBiometrics
- (void)checkTouchID{
LAContext *laContext = [[LAContext alloc] init];
//去掉 “輸入密碼”
laContext.localizedFallbackTitle = @"";
NSError *error;
if ([laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
NSLog(@"指紋識別有效");
}else {
NSLog(@"指紋識別無效%@",error.localizedDescription);
}
}
iOS8系統:
在只有口令密碼的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
在只有指紋的情況下打印結果: NSLog(@"指紋識別無效%@",error.localizedDescription);
在沒有口令也沒有指紋的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
iOS9系統:
在只有口令密碼的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
在只有指紋的情況下打印結果: NSLog(@"指紋識別無效%@",error.localizedDescription);
在沒有口令也沒有指紋的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
iOS10系統:
在只有口令密碼的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
在只有指紋的情況下打印結果: NSLog(@"指紋識別無效%@",error.localizedDescription);
在沒有口令也沒有指紋的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
分析可知,在LAPolicyDeviceOwnerAuthenticationWithBiometrics
下必須系統口令碼和指紋同時是存在的,才會判定指紋系統是可用的。
LAPolicyDeviceOwnerAuthentication
- (void)checkTouchID{
LAContext *laContext = [[LAContext alloc] init];
//去掉 “輸入密碼”
laContext.localizedFallbackTitle = @"";
NSError *error;
if ([laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error]) {
NSLog(@"指紋識別有效");
}else {
NSLog(@"指紋識別無效%@",error.localizedDescription);
}
}
iOS9系統:
在只有口令密碼的情況下打印結果:NSLog(@"指紋識別有效");
在只有指紋的情況下打印結果: NSLog(@"指紋識別無效%@",error.localizedDescription);
在沒有口令也沒有指紋的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
iOS10系統:
在只有口令密碼的情況下打印結果:NSLog(@"指紋識別有效");
在只有指紋的情況下打印結果: NSLog(@"指紋識別無效%@",error.localizedDescription);
在沒有口令也沒有指紋的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
綜合iOS9、iOS10在policy:LAPolicyDeviceOwnerAuthentication
下的表現,只要開啟了系統口令碼,就判定指紋系統可用,更加印證了 如果沒有開啟設備密碼,則不可以使用這種驗證方式。
指紋鑒定錯誤碼
1、 驗證(指紋/密碼)不能開啟的錯誤信息(指紋系統被判定為無效):
LAErrorPasscodeNotSet : 設備密碼未設置
LAErrorTouchIDNotAvailable : TOUCH ID不可用
LAErrorTouchIDNotEnrolled : 指紋未錄入
LAErrorTouchIDLockout : TOUCH ID被鎖定
LAErrorAppCancel : APP調用了- (void)invalidate
方法使LAContext
失效
LAErrorInvalidContext : 實例化的LAContext
對象失效,再次調用evaluation...
方法則會彈出此錯誤信息
2、 其他錯誤信息(指紋系統判定有效,但是驗證指紋錯誤):
LAErrorAuthenticationFailed : 鑒定失敗
LAErrorUserCancel : 用戶取消
LAErrorUserFallback : 用戶選擇輸入密碼
LAErrorSystemCancel : 系統取消(如:另外一個應用進入前臺)
總結
上面分析了指紋識別的兩種policy在不同系統上、不同狀態下的各種響應狀態,并且列出了一些指紋鑒定錯誤碼,相信對整個API的作用有詳盡的認識,開發出類似支付寶指紋識別的流程也不是難事,希望可以幫助更多人。