iOS 生物識(shí)別 Touch ID&FaceID

簡(jiǎn)介

Touch ID是蘋果公司的一種指紋識(shí)別技術(shù),從iPhone 5s開始,早已為人們所熟知。

Touch ID不存儲(chǔ)用戶的任何指紋圖像,只保存代表指紋的數(shù)字字符。蘋果公司提供Touch ID給第三方應(yīng)用程序使用,程序只會(huì)收到認(rèn)證是否成功的通知,而無(wú)法訪問 Touch ID 或與已注冊(cè)指紋相關(guān)的數(shù)據(jù),這一點(diǎn)對(duì)安全而言尤為重要。

現(xiàn)在有很多銀行類APP、涉及到支付類的APP都集成了指紋、手勢(shì)等二次驗(yàn)證功能,從而使APP獲得更高的安全性。今天我們就來(lái)分析一下指紋識(shí)別登錄功能的具體實(shí)現(xiàn)。

實(shí)現(xiàn)步驟

1.首先引入指紋解鎖的庫(kù)文件

#import <LocalAuthentication/LocalAuthentication.h>

2.兩個(gè)主要方法

///這個(gè)方法是判斷設(shè)備是否支持TouchID的
- (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError * __autoreleasing *)error __attribute__((swift_error(none)))
    API_AVAILABLE(macos(10.10), ios(8.0), watchos(3.0), tvos(10.0));
///這個(gè)是用來(lái)驗(yàn)證TouchID的,會(huì)有彈出框出來(lái)
- (void)evaluatePolicy:(LAPolicy)policy
       localizedReason:(NSString *)localizedReason
                 reply:(void(^)(BOOL success, NSError * __nullable error))reply
    API_AVAILABLE(macos(10.10), ios(8.0), watchos(3.0), tvos(10.0));

3.核心源碼

- (void)touchID {
    
    //創(chuàng)建LAContext
    LAContext *context = [LAContext new];
    
    //這個(gè)屬性是設(shè)置指紋輸入失敗之后的彈出框的選項(xiàng)
    context.localizedFallbackTitle = @"沒有忘記密碼";
    
    ///錯(cuò)誤信息
    NSError *error = nil;
    ///這個(gè)方法是判斷設(shè)備是否支持TouchID的
    BOOL isUseTouchID = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
    if (isUseTouchID) {
        NSLog(@"支持指紋識(shí)別");
        //這個(gè)是用來(lái)驗(yàn)證TouchID的,會(huì)有彈出框出來(lái)
        [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"請(qǐng)按home鍵指紋登錄" reply:^(BOOL success, NSError * _Nullable error) {
            if (success) {
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"驗(yàn)證成功");
                });
                
            }else{
                NSLog(@"%@",error.localizedDescription);
                switch (error.code) {
                    case LAErrorSystemCancel:
                    {
                        NSLog(@"系統(tǒng)取消授權(quán),如其他APP切入");
                        break;
                    }
                    case LAErrorUserCancel:
                    {
                        NSLog(@"用戶取消驗(yàn)證Touch ID");
                        break;
                    }
                    case LAErrorAuthenticationFailed:
                    {
                        NSLog(@"授權(quán)失敗");
                        break;
                    }
                    case LAErrorPasscodeNotSet:
                    {
                        NSLog(@"系統(tǒng)未設(shè)置密碼");
                        break;
                    }
                    case LAErrorBiometryNotAvailable:
                    {
                        NSLog(@"設(shè)備Touch ID不可用,例如未打開");
                        break;
                    }
                    case LAErrorBiometryNotEnrolled:
                    {
                        NSLog(@"設(shè)備Touch ID不可用,用戶未錄入");
                        break;
                    }
                    case LAErrorUserFallback:
                    {
                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                            NSLog(@"用戶選擇輸入密碼,切換主線程處理");
                        }];
                        break;
                    }
                    default:
                    {
                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                            NSLog(@"其他情況,切換主線程處理");
                        }];
                        break;
                    }
                }
            }
        }];
    }else{
        NSLog(@"不支持指紋識(shí)別");
        switch (error.code) {
            case LAErrorBiometryNotEnrolled:
            {
                NSLog(@"TouchID is not enrolled TouchID未注冊(cè)");
                break;
            }
            case LAErrorPasscodeNotSet:
            {
                NSLog(@"A passcode has not been set 未設(shè)置密碼");
                break;
            }
            default:
            {
                NSLog(@"TouchID not available TouchID不可用");
                break;
            }
        }
        
        NSLog(@"%@",error.localizedDescription);
    }
    
}

原文鏈接:iOS 指紋識(shí)別登錄功能實(shí)現(xiàn)

============

項(xiàng)目中的優(yōu)化

實(shí)際項(xiàng)目中這個(gè)業(yè)務(wù)實(shí)現(xiàn)的難點(diǎn)在于,首次登錄成功并啟用指紋授權(quán)--->退出APP后--->二次啟動(dòng)APP,如何判斷是否要啟用指紋登錄驗(yàn)證呢?這時(shí)就需要我們對(duì)數(shù)據(jù)持久化和數(shù)據(jù)共享有較深的理解,很多APP開發(fā)者,在開發(fā)登錄保持的時(shí)候,大都會(huì)使用持久化數(shù)據(jù)的方式,存儲(chǔ)成功登錄的標(biāo)記。但對(duì)于安全性較高的APP,每次重新啟動(dòng)時(shí)都會(huì)校驗(yàn)登錄狀態(tài),單靠持久化數(shù)據(jù)是不夠的。

我的解決方案是:
通過三個(gè)數(shù)據(jù)進(jìn)行登錄保持

loginState:持久化數(shù)據(jù),用于存儲(chǔ)用戶登錄成功,未激活狀態(tài);
startAutoLoginState:持久化數(shù)據(jù),是否開啟指紋識(shí)別授權(quán);
isAppCurrentLoginState:共享數(shù)據(jù),登錄激活狀態(tài),該狀態(tài)的特點(diǎn),每次重新啟動(dòng)APP都會(huì)重新初始化數(shù)據(jù)。


原文鏈接:iOS指紋識(shí)別登錄流程及實(shí)現(xiàn)

typedef NS_ENUM(NSInteger, LAError)
{
    //身份驗(yàn)證不成功,因?yàn)橛脩魺o(wú)法提供有效的憑據(jù)。
    LAErrorAuthenticationFailed = kLAErrorAuthenticationFailed,

    //認(rèn)證被用戶取消(例如了取消按鈕)。
    LAErrorUserCancel = kLAErrorUserCancel,

    //認(rèn)證被取消了,因?yàn)橛脩衾没赝税粹o(輸入密碼)。
    LAErrorUserFallback = kLAErrorUserFallback,

    //身份驗(yàn)證被系統(tǒng)取消了(如另一個(gè)應(yīng)用程序去前臺(tái))。
    LAErrorSystemCancel = kLAErrorSystemCancel,

    //身份驗(yàn)證無(wú)法啟動(dòng),因?yàn)樵O(shè)備沒有設(shè)置密碼。
    LAErrorPasscodeNotSet = kLAErrorPasscodeNotSet,

    //身份驗(yàn)證無(wú)法啟動(dòng),因?yàn)橛|摸ID不可用在設(shè)備上。
    LAErrorTouchIDNotAvailable NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use LAErrorBiometryNotAvailable") = kLAErrorTouchIDNotAvailable,

    //身份驗(yàn)證無(wú)法啟動(dòng),因?yàn)闆]有登記的手指觸摸ID。
    LAErrorTouchIDNotEnrolled NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use LAErrorBiometryNotEnrolled") = kLAErrorTouchIDNotEnrolled,

    //驗(yàn)證不成功,因?yàn)橛刑嗟氖〉挠|摸ID嘗試和觸///摸現(xiàn)在ID是鎖著的。
    //解鎖TouchID必須要使用密碼,例如調(diào)用LAPolicyDeviceOwnerAuthenti//cationWithBiometrics的時(shí)候密碼是必要條件。
    //身份驗(yàn)證不成功,因?yàn)橛刑嗍〉挠|摸ID嘗試和觸摸ID現(xiàn)在被鎖定。
    LAErrorTouchIDLockout NS_ENUM_DEPRECATED(10_11, 10_13, 9_0, 11_0, "use LAErrorBiometryLockout")
    __WATCHOS_DEPRECATED(3.0, 4.0, "use LAErrorBiometryLockout") __TVOS_DEPRECATED(10.0, 11.0, "use LAErrorBiometryLockout") = kLAErrorTouchIDLockout,

    //應(yīng)用程序取消了身份驗(yàn)證(例如在進(jìn)行身份驗(yàn)證時(shí)調(diào)用了無(wú)效)。
    LAErrorAppCancel NS_ENUM_AVAILABLE(10_11, 9_0) = kLAErrorAppCancel,

    //LAContext傳遞給這個(gè)調(diào)用之前已經(jīng)失效。
    LAErrorInvalidContext NS_ENUM_AVAILABLE(10_11, 9_0) = kLAErrorInvalidContext,

    //身份驗(yàn)證無(wú)法啟動(dòng),因?yàn)樯镒R(shí)別驗(yàn)證在當(dāng)前這個(gè)設(shè)備上不可用。
    LAErrorBiometryNotAvailable NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryNotAvailable,

    //身份驗(yàn)證無(wú)法啟動(dòng),因?yàn)樯镒R(shí)別沒有錄入信息。
    LAErrorBiometryNotEnrolled NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryNotEnrolled,

    //身份驗(yàn)證不成功,因?yàn)樘啻蔚尿?yàn)證失敗并且生物識(shí)別驗(yàn)證是鎖定狀態(tài)。此時(shí),必須輸入密碼才能解鎖。例如LAPolicyDeviceOwnerAuthenticationWithBiometrics時(shí)候?qū)⒚艽a作為先決條件。
    LAErrorBiometryLockout NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryLockout,

    //身份驗(yàn)證失敗。因?yàn)檫@需要顯示UI已禁止使用interactionNotAllowed屬性。  據(jù)說(shuō)是beta版本
    LAErrorNotInteractive API_AVAILABLE(macos(10.10), ios(8.0), watchos(3.0), tvos(10.0)) = kLAErrorNotInteractive,
} NS_ENUM_AVAILABLE(10_10, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0);


FaceID

注意要添加權(quán)限

Privacy - Face ID Usage Description

1.首先引入指紋解鎖的庫(kù)文件

#import <LocalAuthentication/LocalAuthentication.h>

2.核心源碼

-(void)faceID{
        NSError *error;
        
        LAContext *context = [[LAContext alloc]init];
        
        BOOL canAuthentication = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];
        if (canAuthentication) {
            
            [context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:@"FaceID驗(yàn)證" reply:^(BOOL success, NSError * _Nullable error) {
                //注意iOS 11.3之后需要配置Info.plist權(quán)限才可以通過Face ID驗(yàn)證哦!不然只能輸密碼啦...
                if (success) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        NSLog(@"驗(yàn)證成功");
                    });
                } else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        NSLog(@"當(dāng)前軟件被掛起并取消了授權(quán) (如App進(jìn)入了后臺(tái)等)");
                        NSLog(@"error-->%@",error);
                    });
                    
                }
            }];
        }
}

========
判斷設(shè)備是否支持TouchID 和 FaceID

-(void)justTouchIDFaceID{
    
    // 檢測(cè)設(shè)備是否支持TouchID或者FaceID
        if (@available(iOS 8.0, *)) {
            LAContext *LAContent = [[LAContext alloc] init];

            NSError *authError = nil;
            BOOL isCanEvaluatePolicy = [LAContent canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError];

            if (authError) {
                NSLog(@"檢測(cè)設(shè)備是否支持TouchID或者FaceID失?。n error : == %@",authError.localizedDescription);
            } else {
                if (isCanEvaluatePolicy) {
                    // 判斷設(shè)備支持TouchID還是FaceID
                    if (@available(iOS 11.0, *)) {
                        switch (LAContent.biometryType) {
                            case LABiometryTypeNone:
                            {
                                NSLog(@"The device does not support biometry.");
                            }
                                break;
                            case LABiometryTypeTouchID:
                            {
                                NSLog(@"The device supports Touch ID.");
                            }
                                break;
                            case LABiometryTypeFaceID:
                            {
                                NSLog(@"The device supports Face ID.");
                            }
                                break;
                            default:
                                break;
                        }
                    } else {
                        // Fallback on earlier versions
                        NSLog(@"iOS 11之前不需要判斷 biometryType");
                        // 因?yàn)閕PhoneX起始系統(tǒng)版本都已經(jīng)是iOS11.0,所以iOS11.0系統(tǒng)版本下不需要再去判斷是否支持faceID,直接走支持TouchID邏輯即可。
                        NSLog(@"The device supports Face ID.");
                    }

                } else {
                    NSLog(@"The device does not support biometry.");
                }
            }

        } else {
            // Fallback on earlier versions
            NSLog(@"The device does not support biometry.");
        }
    
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 由于自己的產(chǎn)品接下來(lái)可能要支持touch id,所以有必要對(duì)ios的指紋識(shí)別做一下預(yù)研。去年九月份,隨著 iPho...
    JonnyHoang閱讀 1,408評(píng)論 0 6
  • 簡(jiǎn)介 Touch ID是蘋果公司的一種指紋識(shí)別技術(shù),從iPhone 5s開始,早已為人們所熟知。 Touch ID...
    Swift社區(qū)閱讀 2,509評(píng)論 0 4
  • 指紋登陸 隨著智能時(shí)代的來(lái)臨,人們?cè)絹?lái)越習(xí)慣于將重要信息和個(gè)人隱私存放于智能手機(jī)中。這時(shí)手機(jī)數(shù)據(jù)的安全性就變得尤其...
    sz_藍(lán)天使者閱讀 2,735評(píng)論 0 0
  • 實(shí)用原理: 指紋識(shí)別技術(shù)就是把一個(gè)人同他的指紋對(duì)應(yīng)起來(lái),通過比較他的指紋和預(yù)先保存的指紋進(jìn)行比較,就可以驗(yàn)證他的真...
    艷曉閱讀 3,299評(píng)論 0 18
  • 簡(jiǎn)介 iPhone 5s~iPhone 8都可以通過指紋進(jìn)行解鎖,省去了反復(fù)輸入密碼的繁瑣程序,這個(gè)就是Touch...
    JQWONG閱讀 894評(píng)論 0 4

友情鏈接更多精彩內(nèi)容