TouchID 指紋識別是iPhone 5s設備新增的一項重大功能,用于數據加密和安全。而在IOS 8.0 以后也向第三方開放了相應功能API,我們可以利用這個API做相應的用戶驗證和登錄的功能,省去輸入密碼的環節,提高登錄的用戶體驗。
在app中集成指紋識別是跟系統解鎖iPhone用的一套指紋識別,就是說假如在app中指紋識別錯誤了5次(iOS 系統默認指紋識別錯誤5次后,指紋識別會被判定為無效狀態),那么不僅app中的指紋識別系統是無效的,系統的iPhone指紋識別解鎖系統也是無效的,必須輸入iPhone解鎖口令碼驗證之后,指紋識別才會被系統重新判別為有效!
我在這里說下指紋登錄的流程:
在設備第一次使用指紋登錄之前,必須先登錄原有的賬號
在密碼管理中,點擊開啟“指紋登錄”;
驗證TouchID:檢測當前設備是否支持TouchID,若支持則發起TouchID驗證;
生成設備賬號/密碼:TouchID驗證通過后,根據當前已登錄的賬號和硬件設備Token,生成設備賬號/密碼(規則可自定,密碼要長要復雜),并保存在keychain;
綁定:生成設備賬號/密碼后,將原賬號及設備賬號/密碼,加密后(題主使用的是RSA加密)發送到服務端進行綁定;
成功:驗證原賬號及設備賬號有效后,返回相應狀態,綁定成功則完成整個TouchID(設備)綁定流程。
設備(指紋)登陸
在設備(用戶)綁定之后,并且用戶賬號退出后,可以使用指紋登錄,若當前設備未綁定,則不會出現“指紋登錄”按鈕
TouchID登錄:在用戶登錄界面,點擊“指紋登錄”;
驗證TouchID:檢測當前設備是否支持TouchID,若支持則發起TouchID驗證;
登錄:讀取app在本機的設備賬號/密碼,調用設備登錄接口,發起登錄請求;
成功:驗證設備賬號/密碼后,返回相應狀態,登錄成功則完成整個TouchID登錄流程。
*在設備(用戶)綁定之后,并且當前正處于登錄狀態,也可以將本設備取消綁定,流程基本與綁定流程雷同,不再重復。
具體用法如下:
導入頭文件
#import <LocalAuthentication/LocalAuthentication.h>
使用LocalAuthentication中的LAContext.h和LAError.h兩個頭文件,LAError.h提供錯誤碼
初始化LAContext對象(創建安全驗證對象)
LAContext *context = [[LAContext alloc] init];
LAPolicy這個屬性是一個枚舉,它提供兩個值:
LAPolicyDeviceOwnerAuthenticationWithBiometrics是生物指紋識別。支持iOS 8以上系統,使用該設備的TouchID進行驗證,當輸入TouchID驗證5次失敗后,TouchID被鎖定,只能通過鎖屏后解鎖設備時輸入正確的解鎖密碼來解鎖TouchID。驗證彈框有兩個按鈕,第一個是取消按鈕,第二個按鈕可以自定義標題名稱(默認是"輸入密碼")。只有在第一次指紋驗證失敗后才會出現第二個按鈕,這種鑒定方式的第二個按鈕的功能自定義,第二個按鈕的功能不做處理的話不會有任何響應。
LAPolicyDeviceOwnerAuthentication是生物指紋識別或系統密碼驗證。支持iOS9以上系統,對于8.0系統的手機不能使用。如果TOUCH ID 可用,且已經錄入指紋,則優先調用指紋驗證。其次是調用系統密碼驗證,如果沒有開啟設備密碼,則不可以使用這種驗證方式。指紋識別驗證失敗三次將自動彈出設備密碼輸入框,如果不進行密碼輸入。再次進來還可以有兩次機會驗證指紋,如果都失敗則TOUCH ID被鎖住。以后也只能彈出設備密碼輸入框。補充:值得注意的是在iOS9系統中,前三次驗證失敗會自動彈出密碼驗證框,后兩次驗證失敗后不會自動彈出密碼驗證框。而在iOS 10系統中,前三次驗證失敗或者后兩次驗證失敗,都會自動彈出密碼驗證框。
看下兩種驗證方式在各系統中的執行情況
LAPolicyDeviceOwnerAuthenticationWithBiometrics
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
iOS9系統:
在只有口令密碼的情況下打印結果:NSLog(@"指紋識別有效");
在只有指紋的情況下打印結果: NSLog(@"指紋識別無效%@",error.localizedDescription);
在沒有口令也沒有指紋的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
iOS10系統:
在只有口令密碼的情況下打印結果:NSLog(@"指紋識別有效");
在只有指紋的情況下打印結果: NSLog(@"指紋識別無效%@",error.localizedDescription);
在沒有口令也沒有指紋的情況下打印結果:NSLog(@"指紋識別無效%@",error.localizedDescription);
綜合iOS9、iOS10在policy:LAPolicyDeviceOwnerAuthentication下的表現,只要開啟了系統口令碼,就判定指紋系統可用,更加印證了 如果沒有開啟設備密碼,則不可以使用這種驗證方式。
官方API僅提供TouchID的支持狀態和驗證狀態:
canEvaluatePolicy
監測設備是否支持TouchID,返回BOOL,并且若不支持,則在error里面返回相應狀態
evaluatePolicy
監測TouchID驗證狀態,若驗證錯誤則在block里面返回驗證狀態和error錯誤原因
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//創建安全驗證對象
LAContext *context = [[LAContext alloc] init];
//不設置,默認是取消
context.localizedCancelTitle = @"切換其他支付方式";
//不設置的話,驗證失敗會顯示輸入密碼的按鈕,設置了就沒有這個按鈕
context.localizedFallbackTitle = @"";
//錯誤對象
NSError *error = nil;
NSString *result = @"請驗證已有指紋";
//判斷支持 touch ID
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error]) {
//可以調用 touch ID
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:result reply:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"touch ID 正確,回主線程刷新UI");
// dispatch_async(dispatch_get_main_queue(), ^{
// });
}else{
if(error.code == kLAErrorBiometryLockout) {
NSLog(@"連續五次指紋識別錯誤,TouchID功能被鎖定,下一次需要輸入系統密碼");
[context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:result reply:^(BOOL success, NSError * _Nullable error) {
if (success) {
NSLog(@"---系統密碼正確");
}else{
NSLog(@"---系統密碼錯誤5次后,要延遲等待時間了");
}
}];
}else
if(error.code == LAErrorAppCancel) {
NSLog(@"認證被取消了由用戶(例如了取消按鈕");
}else if(error.code == LAErrorInvalidContext) {
NSLog(@"LAContext傳遞給這個調用之前已經失效(請求驗證出錯)");
}else if(error.code == LAErrorAuthenticationFailed) {
NSLog(@"連續三次指紋識別錯誤");
}else if (error.code == LAErrorUserFallback){
NSLog(@"用戶選擇輸入密碼,切換主線程處理");
}else if (error.code == LAErrorSystemCancel){
NSLog(@"身份驗證被系統取消了(如另一個應用程序去前臺)。");
}else if (error.code == LAErrorPasscodeNotSet){
NSLog(@"設備系統未設置密碼");
}else if (error.code == kLAErrorTouchIDNotAvailable){
NSLog(@"設備未設置Touch ID,因為設備上無法使用Touch ID。");
}else if (error.code == kLAErrorTouchIDNotEnrolled){
NSLog(@"用戶未錄入指紋");
}else if (error.code == LAErrorUserCancel){
NSLog(@"用戶點擊了取消----更換支付方式");
}else{
NSLog(@"原因未知");
}
}
}];
}else{
NSLog(@"不支持touch ID ,只能用密碼了");
}
}