iOS指紋識別

指紋登陸

隨著智能時代的來臨匆帚,人們越來越習(xí)慣于將重要信息和個人隱私存放于智能手機中。這時手機數(shù)據(jù)的安全性就變得尤其重要。通常我們使用口令或密碼來保護設(shè)備去团,但是隨著iPhone和Android手機硬件的逐步升級與支持文搂,使用指紋驗證成為了代替密碼的一種常規(guī)方法适刀。

指紋驗證是指通過手機中的觸摸傳感器來識別用戶。通過這種技術(shù)我們可以使用指紋解鎖設(shè)備或在應(yīng)用中通過指紋授權(quán)使用例如指紋登錄或指紋支付等功能煤蹭。

為什么使用指紋驗證

對于應(yīng)用而言笔喉,使用指紋驗證可以從多方面提升用戶體驗:

指紋驗證是一種更加快捷方便的方法來驗證用戶身份。傳統(tǒng)校驗用戶身份的方法硝皂,通常是使用密碼或口令然遏,要想越安全就需要使用越復(fù)雜的密碼。相較于輸入冗長且復(fù)雜的密碼吧彪,指紋識別僅僅需要的是使用指尖觸碰傳感器完成驗證待侵。這無疑能給用戶帶來更加順暢的使用體驗。

指紋不會被遺忘姨裸。如上一條所說秧倾,通常密碼都是冗長且復(fù)雜的,尤其是不常使用的密碼傀缩,很容易在一段時間后被用戶忘記那先。而使用指紋識別則完全沒有這種煩惱,你可以隨時使用指紋驗證赡艰。

指紋驗證無需找回功能售淡。由于指紋永遠(yuǎn)不會被遺忘,也不會改變慷垮。通常密碼找回的功能對于指紋驗證來說就毫無意義揖闸。

指紋驗證更加安全。通常為了方便記憶密碼料身,用戶傾向于使用方便記憶的信息(比如生日)來生成密碼汤纸,這讓密碼變得很容易被破解。而即便使用了較為復(fù)雜的密碼芹血,也無法保證其擁有和指紋一樣的獨特性和安全性贮泞。一旦密碼被泄露或盜取,其他人能輕易獲取到用戶信息幔烛。

iOS技術(shù)背景

Touch ID

iOS設(shè)備下的指紋識別是通過iOS設(shè)備提供的Touch ID實現(xiàn)啃擦。

Touch ID技術(shù)包括在iOS設(shè)備上的一套先進(jìn)的硬件與軟件系統(tǒng):

  • 在iOS硬件設(shè)備上的HOME按鍵由藍(lán)寶石水晶制成,能作為透鏡獲取到你手指皮膚下紋理的高清圖片

  • Touch ID會通過你傳入的一系列指紋圖片饿悬,通過算法生成出屬于指紋的數(shù)字標(biāo)識令蛉,存儲于特殊的芯片上

Touch ID只會存儲通過指紋圖片生成的數(shù)字標(biāo)識,所以不用擔(dān)心你真實的指紋泄露乡恕。由于指紋的獨特性言询,Touch ID算出的數(shù)字標(biāo)識能相同的概率是50000之1俯萎,就是50000個不同指紋才可能會有一對可以通過Touch ID相互匹配。所以Touch ID是一項足夠安全的技術(shù)运杭。

Touch ID已經(jīng)備蘋果普遍使用于iTunes Store, App Store和Apple Pay夫啊。微信和支付寶的支付也已經(jīng)使用了Touch ID。所以Touch ID也是一項被廣泛信賴并使用的技術(shù)辆憔。

Secure Enclave

如在介紹Touch ID時介紹的一樣撇眯,Touch ID不會存儲任何關(guān)于指紋的圖片,而是存儲的指紋標(biāo)識虱咧。不過即使是這些數(shù)字標(biāo)識也被iOS存儲于一塊叫做Secure Enclave(安全領(lǐng)域)的芯片上熊榛。你的指紋信息只會被用于比對是否與設(shè)備中存儲的指紋信息進(jìn)行比對,不能被操作系統(tǒng)腕巡,更不會被其他應(yīng)用訪問玄坦。這些信息也不會上傳到蘋果的服務(wù)或者被iCloud等云服務(wù)備份,不可能被用于與其他的指紋庫進(jìn)行比對绘沉。

LocalAuthentication

LocalAuthentication framework是我們的app來使用iOS設(shè)備上生物信息驗證(Touch ID或者Touch ID)的機制煎楣。上文已經(jīng)介紹過,為了最大限度的保護用戶信息的私密性和安全性车伞,iOS上使用了Secure Enclave的方式來將驗證數(shù)據(jù)與設(shè)備上的其他系統(tǒng)隔離择懂。用戶的認(rèn)證信息甚至無法被操作系統(tǒng)訪問,我們通過認(rèn)證得到的只是一條布爾值的結(jié)果另玖。

Keychain

當(dāng)需要存儲私密信息時困曙,你可以使用Keychain。Keychain是由iOS的Security framework提供的服務(wù)谦去,你可以設(shè)置keychain中元素的訪問權(quán)限為每次去讀取這項數(shù)據(jù)時都需要用戶的認(rèn)證(通過Face ID或者Touch ID)慷丽。當(dāng)每次去請求keychian中數(shù)據(jù)訪問權(quán)限時,LocalAuthentiation Framework會通過系統(tǒng)展示相應(yīng)的界面提示用戶錄入數(shù)據(jù)哪轿,然后將這些數(shù)據(jù)傳入Secure Enclave進(jìn)行比對盈魁。比對結(jié)束后,Secure Enclave會成功或失敗的結(jié)果返回窃诉。其間用戶或者操作系統(tǒng)都不會也不能獲取到用戶的指紋信息。

image.png

概述

在iOS和Android技術(shù)背景中我們得知:

我們通過指紋識別能獲取到只是指紋是否匹配赤套,并不能得到其他與指紋信息有關(guān)的結(jié)果

但是我們可以存儲私密信息飘痛,并通過指紋獲取訪問權(quán)限

在此基礎(chǔ)上,初步設(shè)計了指紋識別的流程容握。iOS和安卓在指紋識別上的流程由于API的限制不盡相同宣脉,但是大概的步驟基本一致:

1.打開指紋認(rèn)證界面獲取獲取權(quán)限

2.如果步驟1指紋認(rèn)證成功,獲取到權(quán)限后嘗試從設(shè)備中獲取用戶登錄所需密鑰

3.如果步驟2成功獲取到用戶密鑰剔氏,即用戶已經(jīng)綁定了指紋登陸塑猖,那么獲取用戶密鑰登陸

4.如果步驟2未能獲取到用戶密鑰竹祷,即用戶還未綁定指紋登陸,那么開始綁定指紋的流程

5.綁定指紋的流程可以分為前端和后端的工作羊苟,先由后端生成用戶登陸所需的獨特密鑰傳回給前端

6.前端收到密鑰后將密鑰存儲于本地設(shè)備中

7.使用獲取到的密鑰就能成功登陸

簡化流程如圖:

image.png

iOS實現(xiàn)方案

iOS上的指紋登陸方案的主題內(nèi)容為:

  • 使用Security framework將用戶密鑰信息存儲于keychain中

  • 使用LocalAuthentication framework來驗證用戶指紋信息塑陵,并且獲取到keychain中的密鑰訪問權(quán)限

配置工程

要使用Touch ID和Keychain的功能,首先需要將需要的framework添加到工程中蜡励。打開工程后選擇對應(yīng)的Target后點擊Build Phases > Link Binary With Libraries令花,點擊+號添加LocalAuthentication和Security兩個framework。

image.png

TouchID API使用

1.添加頭文件

#import <LocalAuthentication/LocalAuthentication.h>

2.判斷系統(tǒng)版本

 //首先判斷版本
if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0) {
      NSLog(@"系統(tǒng)版本不支持TouchID");
      return;
}

3.LAPolicy

在這里簡單介紹一下LAPolicy,它是一個枚舉.我們根據(jù)自己的需要選擇LAPolicy凉倚,它提供兩個值:
LAPolicyDeviceOwnerAuthenticationWithBiometricsLAPolicyDeviceOwnerAuthentication.
<1>. LAPolicyDeviceOwnerAuthenticationWithBiometrics是支持iOS8以上系統(tǒng),使用該設(shè)備的TouchID進(jìn)行驗證,當(dāng)輸入TouchID驗證5次失敗后,TouchID被鎖定,只能通過鎖屏后解鎖設(shè)備時輸入正確的解鎖密碼來解鎖TouchID兼都。
<2>.LAPolicyDeviceOwnerAuthentication是支持iOS9以上系統(tǒng),使用該設(shè)備的TouchID或設(shè)備密碼進(jìn)行驗證,當(dāng)輸入TouchID驗證5次失敗后稽寒,TouchID被鎖定扮碧,會觸發(fā)設(shè)備密碼頁面進(jìn)行驗證。

4. canEvaluatePolicy

使用canEvaluatePolicy方法判斷設(shè)備是否支持TouchID杏糙,返回BOOLYES芬萍,該設(shè)備支持TouchID。

 if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {

error為返回驗證錯誤碼.具體不解釋了.

4. evaluatedPolicyDomainState

context.evaluatedPolicyDomainState用于判斷設(shè)備上的指紋是否被更改搔啊,在LAContext被創(chuàng)建的時候柬祠,evaluatedPolicyDomainState才生效,可在TouchID驗證成功時负芋,將它記錄下來漫蛔,用于下次使用TouchID時校驗,提高安全性旧蛾。

5. evaluatePolicy

evaluatePolicy方法是對TouchID進(jìn)行驗證,Block回調(diào)中如果success為YES則驗證成功,為NO驗證失敗,并對error進(jìn)行解析.

- (IBAction)loginButtonClick:(UIButton *)sender {

    //首先判斷版本
    if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0) {
        NSLog(@"系統(tǒng)版本不支持TouchID");
        return;
    }

    LAContext *context = [[LAContext alloc] init];
    context.localizedFallbackTitle = @"輸入密碼";
    if (@available(iOS 10.0, *)) {
//        context.localizedCancelTitle = @"22222";
    } else {
        // Fallback on earlier versions
    }
    NSError *error = nil;

    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {

        [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"通過Home鍵驗證已有手機指紋" reply:^(BOOL success, NSError * _Nullable error) {

            if (success) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"TouchID 驗證成功");
                });
            }else if(error){

                switch (error.code) {
                    case LAErrorAuthenticationFailed:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"TouchID 驗證失敗");
                        });
                        break;
                    }
                    case LAErrorUserCancel:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"TouchID 被用戶手動取消");
                        });
                    }
                        break;
                    case LAErrorUserFallback:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"用戶不使用TouchID,選擇手動輸入密碼");
                        });
                    }
                        break;
                    case LAErrorSystemCancel:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"TouchID 被系統(tǒng)取消 (如遇到來電,鎖屏,按了Home鍵等)");
                        });
                    }
                        break;
                    case LAErrorPasscodeNotSet:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"TouchID 無法啟動,因為用戶沒有設(shè)置密碼");
                        });
                    }
                        break;
                    case LAErrorTouchIDNotEnrolled:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"TouchID 無法啟動,因為用戶沒有設(shè)置TouchID");
                        });
                    }
                        break;
                    case LAErrorTouchIDNotAvailable:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"TouchID 無效");
                        });
                    }
                        break;
                    case LAErrorTouchIDLockout:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"TouchID 被鎖定(連續(xù)多次驗證TouchID失敗,系統(tǒng)需要用戶手動輸入密碼)");
                        });
                    }
                        break;
                    case LAErrorAppCancel:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"當(dāng)前軟件被掛起并取消了授權(quán) (如App進(jìn)入了后臺等)");
                        });
                    }
                        break;
                    case LAErrorInvalidContext:{
                        dispatch_async(dispatch_get_main_queue(), ^{
                            NSLog(@"當(dāng)前軟件被掛起并取消了授權(quán) (LAContext對象無效)");
                        });
                    }
                        break;
                    default:
                        break;
                }
            }
        }];

    }else{
        NSLog(@"當(dāng)前設(shè)備不支持TouchID");
    }
}

上面這個代碼, 是整個TouchID的核心,也幾乎是所有代碼了.

驗證

驗證必須使用真機

image
image

總結(jié):TouchID使用起來不難,重要的是使用流程邏輯.

以登錄為例,一般來說流程是這樣的:
1.開啟指紋登錄:首次登陸使用密碼登錄,登錄后,可以設(shè)置一個開啟指紋ID登錄的按鈕,來進(jìn)行指紋認(rèn)證.
2.驗證:檢測是否支持TouchID.
3.生成設(shè)備賬號/密碼:TouchID驗證通過后莽龟,根據(jù)當(dāng)前已登錄的賬號和硬件設(shè)備Token,生成設(shè)備賬號/密碼(規(guī)則可自定锨天,密碼要長要復(fù)雜)毯盈,并保存在keychain;
4.綁定:生成設(shè)備賬號/密碼后病袄,將原賬號及設(shè)備賬號/密碼搂赋,加密后(題主使用的是RSA加密)發(fā)送到服務(wù)端進(jìn)行綁定;
5.成功:驗證原賬號及設(shè)備賬號有效后益缠,返回相應(yīng)狀態(tài)脑奠,綁定成功則完成整個TouchID(設(shè)備)綁定流程。

注意的坑

在ios10指紋驗證錯誤過多會報錯幅慌,然后不會彈出系統(tǒng)密碼輸入界面:

打印error.code宋欺,是:-8
打印error.localizedDescription,是:Biometry is locked out
上網(wǎng)查到ios9以前會彈出系統(tǒng)密碼輸入界面。

ios10及以后呢齿诞?

ios9以前這樣寫:

//是否支持touchid
[_context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]
//驗證指紋是否匹配
[_context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"通過home鍵驗證已有指紋" reply:^(BOOL success, NSError * _Nullable error) {}

IOS10上只需把上面兩個地方的 LAPolicyDeviceOwnerAuthenticationWithBiometrics
換成
LAPolicyDeviceOwnerAuthentication
即可酸休。

ios10這樣寫

//是否支持touchid
[_context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]
//報錯碼為-8時,調(diào)用此方法會彈出系統(tǒng)密碼輸入界面

[_context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:@"指紋驗證錯誤次數(shù)過多祷杈,請輸入密碼" reply:^(BOOL success, NSError * _Nullable error){

當(dāng)然為了適配ios8,9,10可以在適當(dāng)?shù)臅r候斑司,做適當(dāng)?shù)牟僮鳌?/p>

參考鏈接:
iOS指紋登陸
iOS 指紋登錄(TouchID)集成方案
IOS TouchId開發(fā) Biometry is locked out
iOS指紋識別登錄流程及實現(xiàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吠式,隨后出現(xiàn)的幾起案子陡厘,更是在濱河造成了極大的恐慌,老刑警劉巖特占,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糙置,死亡現(xiàn)場離奇詭異,居然都是意外死亡是目,警方通過查閱死者的電腦和手機谤饭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來懊纳,“玉大人揉抵,你說我怎么就攤上這事∴头瑁” “怎么了冤今?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長茂缚。 經(jīng)常有香客問我戏罢,道長,這世上最難降的妖魔是什么脚囊? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任龟糕,我火速辦了婚禮,結(jié)果婚禮上悔耘,老公的妹妹穿的比我還像新娘讲岁。我一直安慰自己,他們只是感情好衬以,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布缓艳。 她就那樣靜靜地躺著,像睡著了一般泄鹏。 火紅的嫁衣襯著肌膚如雪郎任。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天备籽,我揣著相機與錄音,去河邊找鬼。 笑死车猬,一個胖子當(dāng)著我的面吹牛霉猛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播珠闰,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼惜浅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伏嗜?” 一聲冷哼從身側(cè)響起坛悉,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎承绸,沒想到半個月后裸影,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡军熏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年轩猩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荡澎。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡均践,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出摩幔,到底是詐尸還是另有隱情彤委,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布或衡,位于F島的核電站焦影,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏薇宠。R本人自食惡果不足惜偷办,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澄港。 院中可真熱鬧椒涯,春花似錦、人聲如沸回梧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狱意。三九已至湖苞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間详囤,已是汗流浹背财骨。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工镐作, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人隆箩。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓该贾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捌臊。 傳聞我的和親對象是個殘疾皇子杨蛋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348