指紋驗證完整版處理小結
阿新 • • 發佈:2018-03-29
之前 isp title white emc eal lec emca 技術
在ios中指紋的使用相對比較簡單,但是在使用的過程中遇到以下幾個問題,故對指紋使用進行簡單封裝,以處理這些問題,問題如下:
1、ios 9之後系統指紋被鎖,系統不會主動彈出密碼解鎖的頁面
2、ios 10.*系統不區分指紋未錄入和密碼未設置的情況
處理邏輯如下:
處理部分代碼如下:
----------------------------.h文件 /* 1、處理iOS 9.0之後,指紋被鎖不會自動彈出密碼解鎖的情況; 2、處理iOS 10.*系統不區分未錄入指紋和未設置密碼的情況; */ #import <Foundation/Foundation.h> typedef NS_ENUM(NSInteger, TITouchIDVerificationError) { TITouchIDVerificationErrorLocalizedReason, TITouchIDVerificationErrorAuthFailMessage, TITouchIDVerificationErrorNotAvailableMessage, TITouchIDVerificationErrorNotEnrolledMessage, TITouchIDVerificationErrorLockOut, TITouchIDVerificationErrorPasscodeNotSetMessage, TITouchIDVerificationErrorUserCancel, TITouchIDVerificationErrorAppCancel, TITouchIDVerificationErrorUnknown }; typedef NS_ENUM(NSInteger, TIVerificationStatus) { TIVerificationStatusSuccess, TIVerificationStatusPasswordNotSet, TIVerificationStatusNotEncrolled, TIVerificationStatusFailed, TIVerificationStatusFallback, TIVerificationStatusLockOut, TIVerificationStatusCancel, TIVerificationStatusError, }; typedefvoid(^VerificationCompletion)(TIVerificationStatus status, NSError *error); @interface LYYTouchID : NSObject /** 調用TouchID @param completion 驗證完成,如果返回YES,驗證成功;如果返回NO,驗證失敗(輸入密碼和指紋驗證失敗) */ + (void)touchVerificationWithFallbackTitle:(NSString*)fallbackTitle completion:(VerificationCompletion)completion;@end ---------------------------.m文件 #import "LYYTouchID.h" #import <UIKit/UIKit.h> #import <LocalAuthentication/LocalAuthentication.h> #define TI_IS_iOS_LATER(num) ([UIDevice currentDevice].systemVersion.floatValue >= (num)) #define TI_IS_iOS8_LATER TI_IS_iOS_LATER(8.0) #define TI_IS_iOS9_LATER TI_IS_iOS_LATER(9.0) #defineTI_IS_iOS10_LATER TI_IS_iOS_LATER(10.0) #define TI_IS_iOS11_LATER TI_IS_iOS_LATER(11.0) NSString * const TouchIDLocalizedReason = @"請您驗證已有TouchID"; NSString * const TouchIDNotAvailableMessage = @"您當前設備不支持TouchID"; NSString * const TouchIDNotEnrolledMessage = @"您當前沒有錄入指紋信息"; NSString * const TouchIDNotCorrectMessage = @"您的指紋信息不匹配"; NSString * const TouchIDPasscodeNotSetMessage = @"您當前沒有設置密碼"; NSString * const TouchIDCancelMessage = @"您已取消驗證TouchID"; NSString * const TouchIDUnknownErrorMessage = @"出現未知錯誤"; NSString * const TouchIDLockOutMessage = @"TouchID 被鎖定"; static BOOL _isTouchIDLocked;//用於存儲第一遍canEvaluatePolicy檢查到的指紋被鎖的狀態 static BOOL _touchIDSecondCheck;//用於存儲canEvaluatePolicy是否是第二次查詢 @interface LYYTouchID () @end @implementation LYYTouchID #pragma mark - 驗證 + (void)touchVerificationWithFallbackTitle:(NSString*)fallbackTitle completion:(VerificationCompletion)completion{ LAContext *context = [[LAContext alloc] init]; context.localizedFallbackTitle = fallbackTitle?:@""; LAPolicy policy = [self setPolicy]; NSError *notSupportError = nil; if ([context canEvaluatePolicy:policy error:¬SupportError]) { //處理10.*系統純指紋策略不走passwordNotSet方法 if (_touchIDSecondCheck&&TI_IS_iOS10_LATER&&!TI_IS_iOS11_LATER) {//第二次檢測指紋是否可用(指紋+密碼策略),且可以 _touchIDSecondCheck = NO; completion(TIVerificationStatusNotEncrolled,[self returnErrorInfoWithErrorCode:LAErrorTouchIDNotEnrolled]); return; } //不是第二次檢測指紋是否可用,直接進行驗證 [context evaluatePolicy:policy localizedReason:TouchIDLocalizedReason reply:^(BOOL success, NSError * _Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ if (success) { if (TI_IS_iOS9_LATER&&_isTouchIDLocked) {//TouchID 解鎖成功時,更改為純指紋策略,驗證TouchID _isTouchIDLocked = NO; [self touchVerificationWithFallbackTitle:fallbackTitle completion:completion]; }else{//ios9.0之前版本不支持密碼策略直接返回信息 _isTouchIDLocked = NO; completion(TIVerificationStatusSuccess,nil); } } else { int code = (int)error.code; ////設置鎖定狀態為NO _isTouchIDLocked = NO; [self dealErrorWithErrorCode:code fallbackTitle:fallbackTitle complection:completion]; } }); }]; }else { [self dealErrorWithErrorCode:(int)notSupportError.code fallbackTitle:fallbackTitle complection:completion]; } } #pragma mark - 設置指紋策略 + (LAPolicy)setPolicy{ LAPolicy policy; if (_touchIDSecondCheck&&TI_IS_iOS9_LATER){//已經查驗過純指紋策略,且純指紋策略不支持,改變策略為指紋+密碼進行二次驗證 policy = LAPolicyDeviceOwnerAuthentication; return policy; } if (_isTouchIDLocked&&TI_IS_iOS9_LATER) {//指紋被鎖定且系統大於9.0,使用“指紋+密碼”策略 policy = LAPolicyDeviceOwnerAuthentication; }else{//使用“指紋”策略(默認是指紋策略) policy = LAPolicyDeviceOwnerAuthenticationWithBiometrics; } return policy; } #pragma mark - 處理不同錯誤 + (void)dealErrorWithErrorCode:(int)code fallbackTitle:(NSString*)fallbackTitle complection:(VerificationCompletion)completion{ switch (code) { case LAErrorUserFallback: completion(TIVerificationStatusFallback,[self returnErrorInfoWithErrorCode:code]); break; case LAErrorAuthenticationFailed: completion(TIVerificationStatusFailed,[self returnErrorInfoWithErrorCode:code]); break; case LAErrorSystemCancel:{ _isTouchIDLocked = NO; _touchIDSecondCheck = NO; } break; case LAErrorPasscodeNotSet: _isTouchIDLocked = NO; _touchIDSecondCheck = NO; completion(TIVerificationStatusPasswordNotSet,[self returnErrorInfoWithErrorCode:code]); break; case LAErrorTouchIDNotAvailable: break; case LAErrorAppCancel:{ _isTouchIDLocked = NO; _touchIDSecondCheck = NO; } break; case LAErrorUserCancel: _isTouchIDLocked = NO; _touchIDSecondCheck = NO; completion(TIVerificationStatusCancel,[self returnErrorInfoWithErrorCode:code]); break; default: { if (TI_IS_iOS9_LATER) { if (code==LAErrorTouchIDLockout) { //ios9.0更改為密碼策略,解鎖TouchID _isTouchIDLocked = YES; [self touchVerificationWithFallbackTitle:fallbackTitle completion:completion]; break; } } if (TI_IS_iOS8_LATER&&!TI_IS_iOS11_LATER) { if (code==LAErrorTouchIDNotEnrolled) { //處理ios 10.*系統不走passwordNotSet if (TI_IS_iOS10_LATER&&!_touchIDSecondCheck) {//ios 9.0之後,第一次返回指紋不可用的結果(這時是純指紋策略) _touchIDSecondCheck = YES; [self touchVerificationWithFallbackTitle:fallbackTitle completion:completion]; }else{ //ios 9.0 之後是第二次返回不可用結果,此時采用的是指紋+密碼策略,此時指紋確實不可用 //ios 9.0 之前,第一次返回指紋不可用的結果,此時直接返回指紋不可用的錯誤 _touchIDSecondCheck = NO; completion(TIVerificationStatusNotEncrolled,[self returnErrorInfoWithErrorCode:code]); } break; } } if (@available(iOS 11.0, *)) { if (code==LAErrorBiometryNotEnrolled) { completion(TIVerificationStatusNotEncrolled,[self returnErrorInfoWithErrorCode:code]); break; } } completion(TIVerificationStatusError,[self returnErrorInfoWithErrorCode:code]); } break; } } #pragma mark - 生成error + (NSError *)returnErrorInfoWithErrorCode:(int)errorCode { if (TI_IS_iOS9_LATER) { if (errorCode == LAErrorAppCancel) { NSError *tempError = [NSError errorWithDomain:@"TouchIDVerfityDomain" code:TITouchIDVerificationErrorAppCancel userInfo:@{@"message":TouchIDCancelMessage}]; return tempError; } } NSString *errorMessage = @""; NSUInteger errCode = 0; switch (errorCode) { case LAErrorTouchIDNotAvailable: errorMessage = TouchIDNotAvailableMessage; errCode = TITouchIDVerificationErrorNotAvailableMessage; break; case LAErrorAuthenticationFailed: errorMessage = TouchIDNotCorrectMessage; errCode = TITouchIDVerificationErrorAuthFailMessage; break; case LAErrorPasscodeNotSet: errorMessage = TouchIDPasscodeNotSetMessage; errCode = TITouchIDVerificationErrorPasscodeNotSetMessage; break; case LAErrorUserCancel: errorMessage = TouchIDCancelMessage; errCode = TITouchIDVerificationErrorUserCancel; break; default: if (TI_IS_iOS9_LATER) { if (errorCode==LAErrorTouchIDLockout) { errorMessage = TouchIDLockOutMessage; errCode = TITouchIDVerificationErrorLockOut; break; } } if (TI_IS_iOS8_LATER&&!TI_IS_iOS11_LATER) { if (errorCode==LAErrorTouchIDNotEnrolled) { errorMessage = TouchIDNotEnrolledMessage; errCode = TITouchIDVerificationErrorNotEnrolledMessage; break; } } if (@available(iOS 11.0, *)) { if (errorCode==LAErrorBiometryNotEnrolled) { errorMessage = TouchIDNotEnrolledMessage; errCode = TITouchIDVerificationErrorNotEnrolledMessage; break; } } errorMessage = TouchIDUnknownErrorMessage; errCode = TITouchIDVerificationErrorUnknown; break; } NSError *tempError = [NSError errorWithDomain:@"TouchIDVerfityDomain" code:errCode userInfo:@{@"message":errorMessage}]; // return tempError; } @end
指紋驗證完整版處理小結