指紋登陸
隨著智能時代的來臨,人們越來越習慣于將重要信息和個人隱私存放于智能手機中。這時手機數據的安全性就變得尤其重要。通常我們使用口令或密碼來保護設備,但是隨著iPhone和Android手機硬件的逐步升級與支持,使用指紋驗證成為了代替密碼的一種常規方法。
指紋驗證是指通過手機中的觸摸傳感器來識別用戶。通過這種技術我們可以使用指紋解鎖設備或在應用中通過指紋授權使用例如指紋登錄或指紋支付等功能。
為什么使用指紋驗證
對于應用而言,使用指紋驗證可以從多方面提升用戶體驗:
指紋驗證是一種更加快捷方便的方法來驗證用戶身份。傳統校驗用戶身份的方法,通常是使用密碼或口令,要想越安全就需要使用越復雜的密碼。相較于輸入冗長且復雜的密碼,指紋識別僅僅需要的是使用指尖觸碰傳感器完成驗證。這無疑能給用戶帶來更加順暢的使用體驗。
指紋不會被遺忘。如上一條所說,通常密碼都是冗長且復雜的,尤其是不常使用的密碼,很容易在一段時間后被用戶忘記。而使用指紋識別則完全沒有這種煩惱,你可以隨時使用指紋驗證。
指紋驗證無需找回功能。由于指紋永遠不會被遺忘,也不會改變。通常密碼找回的功能對于指紋驗證來說就毫無意義。
指紋驗證更加安全。通常為了方便記憶密碼,用戶傾向于使用方便記憶的信息(比如生日)來生成密碼,這讓密碼變得很容易被破解。而即便使用了較為復雜的密碼,也無法保證其擁有和指紋一樣的獨特性和安全性。一旦密碼被泄露或盜取,其他人能輕易獲取到用戶信息。
iOS技術背景
Touch ID
iOS設備下的指紋識別是通過iOS設備提供的Touch ID實現。
Touch ID技術包括在iOS設備上的一套先進的硬件與軟件系統:
在iOS硬件設備上的HOME按鍵由藍寶石水晶制成,能作為透鏡獲取到你手指皮膚下紋理的高清圖片
Touch ID會通過你傳入的一系列指紋圖片,通過算法生成出屬于指紋的數字標識,存儲于特殊的芯片上
Touch ID只會存儲通過指紋圖片生成的數字標識,所以不用擔心你真實的指紋泄露。由于指紋的獨特性,Touch ID算出的數字標識能相同的概率是50000之1,就是50000個不同指紋才可能會有一對可以通過Touch ID相互匹配。所以Touch ID是一項足夠安全的技術。
Touch ID已經備蘋果普遍使用于iTunes Store, App Store和Apple Pay。微信和支付寶的支付也已經使用了Touch ID。所以Touch ID也是一項被廣泛信賴并使用的技術。
Secure Enclave
如在介紹Touch ID時介紹的一樣,Touch ID不會存儲任何關于指紋的圖片,而是存儲的指紋標識。不過即使是這些數字標識也被iOS存儲于一塊叫做Secure Enclave(安全領域)的芯片上。你的指紋信息只會被用于比對是否與設備中存儲的指紋信息進行比對,不能被操作系統,更不會被其他應用訪問。這些信息也不會上傳到蘋果的服務或者被iCloud等云服務備份,不可能被用于與其他的指紋庫進行比對。
LocalAuthentication
LocalAuthentication framework是我們的app來使用iOS設備上生物信息驗證(Touch ID或者Touch ID)的機制。上文已經介紹過,為了最大限度的保護用戶信息的私密性和安全性,iOS上使用了Secure Enclave的方式來將驗證數據與設備上的其他系統隔離。用戶的認證信息甚至無法被操作系統訪問,我們通過認證得到的只是一條布爾值的結果。
Keychain
當需要存儲私密信息時,你可以使用Keychain。Keychain是由iOS的Security framework提供的服務,你可以設置keychain中元素的訪問權限為每次去讀取這項數據時都需要用戶的認證(通過Face ID或者Touch ID)。當每次去請求keychian中數據訪問權限時,LocalAuthentiation Framework會通過系統展示相應的界面提示用戶錄入數據,然后將這些數據傳入Secure Enclave進行比對。比對結束后,Secure Enclave會成功或失敗的結果返回。其間用戶或者操作系統都不會也不能獲取到用戶的指紋信息。
image.png
概述
在iOS和Android技術背景中我們得知:
我們通過指紋識別能獲取到只是指紋是否匹配,并不能得到其他與指紋信息有關的結果
但是我們可以存儲私密信息,并通過指紋獲取訪問權限
在此基礎上,初步設計了指紋識別的流程。iOS和安卓在指紋識別上的流程由于API的限制不盡相同,但是大概的步驟基本一致:
1.打開指紋認證界面獲取獲取權限
2.如果步驟1指紋認證成功,獲取到權限后嘗試從設備中獲取用戶登錄所需密鑰
3.如果步驟2成功獲取到用戶密鑰,即用戶已經綁定了指紋登陸,那么獲取用戶密鑰登陸
4.如果步驟2未能獲取到用戶密鑰,即用戶還未綁定指紋登陸,那么開始綁定指紋的流程
5.綁定指紋的流程可以分為前端和后端的工作,先由后端生成用戶登陸所需的獨特密鑰傳回給前端
6.前端收到密鑰后將密鑰存儲于本地設備中
7.使用獲取到的密鑰就能成功登陸
簡化流程如圖:
image.png
iOS實現方案
iOS上的指紋登陸方案的主題內容為:
使用Security framework將用戶密鑰信息存儲于keychain中
使用LocalAuthentication framework來驗證用戶指紋信息,并且獲取到keychain中的密鑰訪問權限
配置工程
要使用Touch ID和Keychain的功能,首先需要將需要的framework添加到工程中。打開工程后選擇對應的Target后點擊Build Phases > Link Binary With Libraries,點擊+號添加LocalAuthentication和Security兩個framework。
image.png
TouchID API使用
1.添加頭文件
#import <LocalAuthentication/LocalAuthentication.h>
2.判斷系統版本
//首先判斷版本
if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0) {
NSLog(@"系統版本不支持TouchID");
return;
}
3.LAPolicy
在這里簡單介紹一下LAPolicy
,它是一個枚舉.我們根據自己的需要選擇LAPolicy,它提供兩個值:
LAPolicyDeviceOwnerAuthenticationWithBiometrics
和LAPolicyDeviceOwnerAuthentication
.
<1>. LAPolicyDeviceOwnerAuthenticationWithBiometrics
是支持iOS8以上系統,使用該設備的TouchID進行驗證,當輸入TouchID驗證5次失敗后,TouchID被鎖定,只能通過鎖屏后解鎖設備時輸入正確的解鎖密碼來解鎖TouchID。
<2>.LAPolicyDeviceOwnerAuthentication
是支持iOS9以上系統,使用該設備的TouchID或設備密碼進行驗證,當輸入TouchID驗證5次失敗后,TouchID被鎖定,會觸發設備密碼頁面進行驗證。
4. canEvaluatePolicy
使用canEvaluatePolicy
方法判斷設備是否支持TouchID,返回BOOL
為YES
,該設備支持TouchID。
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
error為返回驗證錯誤碼.具體不解釋了.
4. evaluatedPolicyDomainState
context.evaluatedPolicyDomainState用于判斷設備上的指紋是否被更改,在LAContext被創建的時候,evaluatedPolicyDomainState才生效,可在TouchID驗證成功時,將它記錄下來,用于下次使用TouchID時校驗,提高安全性。
5. evaluatePolicy
evaluatePolicy方法是對TouchID進行驗證,Block回調中如果success為YES則驗證成功,為NO驗證失敗,并對error進行解析.
- (IBAction)loginButtonClick:(UIButton *)sender {
//首先判斷版本
if (NSFoundationVersionNumber < NSFoundationVersionNumber_iOS_8_0) {
NSLog(@"系統版本不支持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 被系統取消 (如遇到來電,鎖屏,按了Home鍵等)");
});
}
break;
case LAErrorPasscodeNotSet:{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"TouchID 無法啟動,因為用戶沒有設置密碼");
});
}
break;
case LAErrorTouchIDNotEnrolled:{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"TouchID 無法啟動,因為用戶沒有設置TouchID");
});
}
break;
case LAErrorTouchIDNotAvailable:{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"TouchID 無效");
});
}
break;
case LAErrorTouchIDLockout:{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"TouchID 被鎖定(連續多次驗證TouchID失敗,系統需要用戶手動輸入密碼)");
});
}
break;
case LAErrorAppCancel:{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"當前軟件被掛起并取消了授權 (如App進入了后臺等)");
});
}
break;
case LAErrorInvalidContext:{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"當前軟件被掛起并取消了授權 (LAContext對象無效)");
});
}
break;
default:
break;
}
}
}];
}else{
NSLog(@"當前設備不支持TouchID");
}
}
上面這個代碼, 是整個TouchID的核心,也幾乎是所有代碼了.
驗證
驗證必須使用真機
總結:TouchID使用起來不難,重要的是使用流程邏輯.
以登錄為例,一般來說流程是這樣的:
1.開啟指紋登錄:首次登陸使用密碼登錄,登錄后,可以設置一個開啟指紋ID登錄的按鈕,來進行指紋認證.
2.驗證:檢測是否支持TouchID.
3.生成設備賬號/密碼:TouchID驗證通過后,根據當前已登錄的賬號和硬件設備Token,生成設備賬號/密碼(規則可自定,密碼要長要復雜),并保存在keychain;
4.綁定:生成設備賬號/密碼后,將原賬號及設備賬號/密碼,加密后(題主使用的是RSA加密)發送到服務端進行綁定;
5.成功:驗證原賬號及設備賬號有效后,返回相應狀態,綁定成功則完成整個TouchID(設備)綁定流程。
注意的坑
在ios10指紋驗證錯誤過多會報錯,然后不會彈出系統密碼輸入界面:
打印error.code,是:-8
打印error.localizedDescription,是:Biometry is locked out
上網查到ios9以前會彈出系統密碼輸入界面。
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時,調用此方法會彈出系統密碼輸入界面
[_context evaluatePolicy:LAPolicyDeviceOwnerAuthentication localizedReason:@"指紋驗證錯誤次數過多,請輸入密碼" reply:^(BOOL success, NSError * _Nullable error){
當然為了適配ios8,9,10可以在適當的時候,做適當的操作。
參考鏈接:
iOS指紋登陸
iOS 指紋登錄(TouchID)集成方案
IOS TouchId開發 Biometry is locked out
iOS指紋識別登錄流程及實現