iOS開發 手勢密碼解鎖和指紋TouchID解鎖

開發仔XG發表於2017-03-17

越來越多的app都是用指紋解鎖(下面都用TouchID表示),現在略微來講解一下TouchID(文末的demo裡TouchID和手勢解鎖都有,這裡只介紹TouchID)

1.系統所使用TouchID的SDK

新增引入LocalAuthentication.framework
framework主要的內容是這個幾個類

- LAContext.h
- LAError.h
- LAPublicDefines.h
- LocalAuthentication.h

使用的時候直接

#import <LocalAuthentication/LocalAuthentication.h>

好了,廢話少說,下面來講主要使用的2個類;

LAError.h

錯誤型別的列舉類,其實是把LAPublicDefines裡的kLAError巨集放入到了這列舉類中,統一了一下,具體程式碼註釋寫的很清晰,在這我加點中文翻譯


typedef NS_ENUM(NSInteger, LAError)
{
    LAErrorAuthenticationFailed,     // 驗證資訊出錯,就是說你指紋不對
    LAErrorUserCancel               // 使用者取消了驗證
    LAErrorUserFallback             // 使用者點選了手動輸入密碼的按鈕,所以被取消了
    LAErrorSystemCancel             // 被系統取消,就是說你現在進入別的應用了,不在剛剛那個頁面,所以沒法驗證
    LAErrorPasscodeNotSet           // 使用者沒有設定TouchID
    LAErrorTouchIDNotAvailable      // 使用者裝置不支援TouchID
    LAErrorTouchIDNotEnrolled       // 使用者沒有設定手指指紋
    LAErrorTouchIDLockout           // 使用者錯誤次數太多,現在被鎖住了
    LAErrorAppCancel                // 在驗證中被其他app中斷
    LAErrorInvalidContext           // 請求驗證出錯
} NS_ENUM_AVAILABLE(10_10, 8_0);

LAContext.h

想要在自己的專案中使用TouchID,就要用到LAContext.h這個類,
最上面的一個列舉

typedef NS_ENUM(NSInteger, LAPolicy)
{
    LAPolicyDeviceOwnerAuthenticationWithBiometrics NS_ENUM_AVAILABLE(NA, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0) = kLAPolicyDeviceOwnerAuthenticationWithBiometrics,
    LAPolicyDeviceOwnerAuthentication NS_ENUM_AVAILABLE(10_11, 9_0) = kLAPolicyDeviceOwnerAuthentication

} NS_ENUM_AVAILABLE(10_10, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0);
第一個列舉LAPolicyDeviceOwnerAuthenticationWithBiometrics就是說,用的是手指指紋去驗證的;NS_ENUM_AVAILABLE(NA, 8_0)iOS8 可用
第二個列舉LAPolicyDeviceOwnerAuthentication少了WithBiometrics則是使用TouchID或者密碼驗證,預設是錯誤兩次指紋或者鎖定後,彈出輸入密碼介面;NS_ENUM_AVAILABLE(10_11, 9_0)iOS 9可用

接下來是幾個例項方法,首先建立LAContext例項物件,使用簡單的[LAContext alloc] init]來建立;

canEvaluatePolicy:error:方法用來檢查當前裝置是否可用touchID,返回一個BOOL值
evaluatePolicy:localizedReason:reply:呼叫驗證方法,注意這裡的三個引數:
第一個引數policy是要使用上面那個LAPolicy的列舉
第二個引數localizedReason是NSString型別的驗證理由
第三個引數reply則是一個回撥Block,block內有一個BOOL型別的success判斷是否成功驗證,還有一個用於判斷錯誤資訊的NSError型別的error
invalidate方法用來廢止這個context

引數localizedReason的具體講解:例如使用的TouchID"XXX"的TouchID 請驗證已有指紋,其中的XXX是你app的name,這黑體字部分無法更改,後面的小字部分請驗證已有指紋可以通過引數localizedReason自定義;

LAContext還有一個localizedFallbackTitle,是用來自定義彈出的alert底部右側的feedback按鈕的title,預設是輸入密碼,如果不想顯示 feedback 按鈕;可以設定 feedBackTitle = @""localizedCancelTitle則是自定義取消按鈕的title,不過localizedCancelTitle系統10.0才能使用;

好了下面上程式碼

LAContext *context = [[LAContext alloc] init];
    context.localizedFallbackTitle = @"驗證登入密碼";
    // LAPolicyDeviceOwnerAuthentication
    __weak __typeof(self)weakSelf = self;
    [context evaluatePolicy:policy localizedReason:@"通過Home鍵驗證已有手機指紋" reply:^(BOOL success, NSError * _Nullable error) {

        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *message = @"";
            if (success) {
                message = @"通過了Touch ID 指紋驗證";
                block(YES, NO, message);
            } else {
                //失敗操作
                LAError errorCode = error.code;
                BOOL inputPassword = NO;
                switch (errorCode) {
                    case LAErrorAuthenticationFailed: {
                        // -1
                        [SVProgressHUD showErrorWithStatus:@"指紋不匹配"];
                        message = @"連續三次指紋識別錯誤";
                    }
                        break;

                    case LAErrorUserCancel: {
                        // -2
                        message = @"使用者取消驗證Touch ID";
                    }
                        break;

                    case LAErrorUserFallback: {
                        // -3
                        inputPassword = YES;
                        message = @"使用者選擇輸入密碼";
                    }
                        break;

                    case LAErrorSystemCancel: {
                        // -4 TouchID對話方塊被系統取消,例如按下Home或者電源鍵
                        message = @"取消授權,如其他應用切入";
                    }
                        break;

                    case LAErrorPasscodeNotSet: {
                        // -5
                        [SVProgressHUD showErrorWithStatus:@"此裝置未設定系統密碼"];
                        message = @"裝置系統未設定密碼";
                    }
                        break;

                    case LAErrorTouchIDNotAvailable: {
                        // -6
                        [SVProgressHUD showErrorWithStatus:@"此裝置不支援 Touch ID"];
                        message = @"此裝置不支援 Touch ID";
                    }
                        break;

                    case LAErrorTouchIDNotEnrolled: {
                        // -7
                        [SVProgressHUD showErrorWithStatus:@"使用者未錄入指紋"];
                        message = @"使用者未錄入指紋";
                    }
                        break;

                    case LAErrorTouchIDLockout: {
                        // -8 連續五次指紋識別錯誤,TouchID功能被鎖定,下一次需要輸入系統密碼
                        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0) {
                            [weakSelf openTouchIDWithPolicy:LAPolicyDeviceOwnerAuthentication touchIDBlock:block];
                        }
                        message = @"Touch ID被鎖,需要使用者輸入密碼解鎖";
                    }
                        break;

                    case LAErrorAppCancel: {
                        // -9 如突然來了電話,電話應用進入前臺,APP被掛起啦
                        message = @"使用者不能控制情況下APP被掛起";
                    }
                        break;

                    case LAErrorInvalidContext: {
                        // -10
                        message = @"Touch ID 失效";
                    }
                        break;

                    default:
                        // [SVProgressHUD showErrorWithStatus:@"此裝置不支援 Touch ID"];
                        break;
                }

            }
        });
    }];

指紋識別的版本問題

1.iOS 9 之前是沒有LAErrorTouchIDLockout鎖定這個選項的,預設錯誤5次後;第6次驗證是自動彈出輸入密碼介面;

2.iOS 9 之後鎖定指紋識別之後,如果需要立即彈出輸入密碼介面需要使用LAPolicyDeviceOwnerAuthentication這個屬性重新發起驗證;

彈窗顯示級別問題

TouchID的彈窗的級別非常之高,高到離譜,經過驗證應用程式內部沒有比指紋識別的window的級別更高的UIWindowLevel,也就說了他是系統級的彈窗。需要注意的是,如果指紋彈窗顯示和消失應用程式會呼叫:

- (void)applicationWillResignActive:(UIApplication *)application;
- (void)applicationDidBecomeActive:(UIApplication *)application;

只要你的app進入後臺或者開啟使用都可以彈出TouchID頁面,具體顯示邏輯視情況判斷;

目前以上程式碼足可以滿足大多數app中TouchID的使用,不足之處敬請指出;
demo地址:https://github.com/XGPASS/XGTouchDemo

參考文章:1.http://www.jianshu.com/p/d44b7d85e0a6
2.http://zcill.com/2016/02/29/LocalAuthentication%E6%BA%90%E7%A0%81%E5%AD%A6%E4%B9%A0/

相關文章