簡介
Touch ID是蘋果公司的一種指紋識別技術(shù),從iPhone 5s開始憔恳,早已為人們所熟知摔刁。
Touch ID不存儲用戶的任何指紋圖像挥转,只保存代表指紋的數(shù)字字符。蘋果公司提供Touch ID給第三方應(yīng)用程序使用共屈,程序只會收到認(rèn)證是否成功的通知绑谣,而無法訪問 Touch ID 或與已注冊指紋相關(guān)的數(shù)據(jù),這一點對安全而言尤為重要拗引。
現(xiàn)在有很多銀行類APP借宵、涉及到支付類的APP都集成了指紋、手勢等二次驗證功能矾削,從而使APP獲得更高的安全性壤玫。今天我們就來分析一下指紋識別登錄功能的具體實現(xiàn)。
實現(xiàn)步驟
1.首先引入指紋解鎖的庫文件
#import <LocalAuthentication/LocalAuthentication.h>
2.兩個主要方法
///這個方法是判斷設(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));
///這個是用來驗證TouchID的哼凯,會有彈出框出來
- (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];
//這個屬性是設(shè)置指紋輸入失敗之后的彈出框的選項
context.localizedFallbackTitle = @"沒有忘記密碼";
///錯誤信息
NSError *error = nil;
///這個方法是判斷設(shè)備是否支持TouchID的
BOOL isUseTouchID = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
if (isUseTouchID) {
NSLog(@"支持指紋識別");
//這個是用來驗證TouchID的垦细,會有彈出框出來
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"請按home鍵指紋登錄" reply:^(BOOL success, NSError * _Nullable error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"驗證成功");
});
}else{
NSLog(@"%@",error.localizedDescription);
switch (error.code) {
case LAErrorSystemCancel:
{
NSLog(@"系統(tǒng)取消授權(quán),如其他APP切入");
break;
}
case LAErrorUserCancel:
{
NSLog(@"用戶取消驗證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(@"不支持指紋識別");
switch (error.code) {
case LAErrorBiometryNotEnrolled:
{
NSLog(@"TouchID is not enrolled TouchID未注冊");
break;
}
case LAErrorPasscodeNotSet:
{
NSLog(@"A passcode has not been set 未設(shè)置密碼");
break;
}
default:
{
NSLog(@"TouchID not available TouchID不可用");
break;
}
}
NSLog(@"%@",error.localizedDescription);
}
}
原文鏈接:iOS 指紋識別登錄功能實現(xiàn)
============
項目中的優(yōu)化
實際項目中這個業(yè)務(wù)實現(xiàn)的難點在于嘱能,首次登錄成功并啟用指紋授權(quán)--->退出APP后--->二次啟動APP吝梅,如何判斷是否要啟用指紋登錄驗證呢?這時就需要我們對數(shù)據(jù)持久化和數(shù)據(jù)共享有較深的理解惹骂,很多APP開發(fā)者苏携,在開發(fā)登錄保持的時候,大都會使用持久化數(shù)據(jù)的方式对粪,存儲成功登錄的標(biāo)記右冻。但對于安全性較高的APP,每次重新啟動時都會校驗登錄狀態(tài)著拭,單靠持久化數(shù)據(jù)是不夠的纱扭。
我的解決方案是:
通過三個數(shù)據(jù)進行登錄保持
loginState:持久化數(shù)據(jù),用于存儲用戶登錄成功儡遮,未激活狀態(tài)乳蛾;
startAutoLoginState:持久化數(shù)據(jù),是否開啟指紋識別授權(quán)鄙币;
isAppCurrentLoginState:共享數(shù)據(jù)肃叶,登錄激活狀態(tài),該狀態(tài)的特點十嘿,每次重新啟動APP都會重新初始化數(shù)據(jù)因惭。
原文鏈接:iOS指紋識別登錄流程及實現(xiàn)
typedef NS_ENUM(NSInteger, LAError)
{
//身份驗證不成功,因為用戶無法提供有效的憑據(jù)绩衷。
LAErrorAuthenticationFailed = kLAErrorAuthenticationFailed,
//認(rèn)證被用戶取消(例如了取消按鈕)筛欢。
LAErrorUserCancel = kLAErrorUserCancel,
//認(rèn)證被取消了,因為用戶利用回退按鈕(輸入密碼)。
LAErrorUserFallback = kLAErrorUserFallback,
//身份驗證被系統(tǒng)取消了(如另一個應(yīng)用程序去前臺)唇聘。
LAErrorSystemCancel = kLAErrorSystemCancel,
//身份驗證無法啟動,因為設(shè)備沒有設(shè)置密碼版姑。
LAErrorPasscodeNotSet = kLAErrorPasscodeNotSet,
//身份驗證無法啟動,因為觸摸ID不可用在設(shè)備上。
LAErrorTouchIDNotAvailable NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use LAErrorBiometryNotAvailable") = kLAErrorTouchIDNotAvailable,
//身份驗證無法啟動,因為沒有登記的手指觸摸ID迟郎。
LAErrorTouchIDNotEnrolled NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use LAErrorBiometryNotEnrolled") = kLAErrorTouchIDNotEnrolled,
//驗證不成功,因為有太多的失敗的觸摸ID嘗試和觸///摸現(xiàn)在ID是鎖著的剥险。
//解鎖TouchID必須要使用密碼,例如調(diào)用LAPolicyDeviceOwnerAuthenti//cationWithBiometrics的時候密碼是必要條件宪肖。
//身份驗證不成功表制,因為有太多失敗的觸摸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)用程序取消了身份驗證(例如在進行身份驗證時調(diào)用了無效)控乾。
LAErrorAppCancel NS_ENUM_AVAILABLE(10_11, 9_0) = kLAErrorAppCancel,
//LAContext傳遞給這個調(diào)用之前已經(jīng)失效么介。
LAErrorInvalidContext NS_ENUM_AVAILABLE(10_11, 9_0) = kLAErrorInvalidContext,
//身份驗證無法啟動,因為生物識別驗證在當(dāng)前這個設(shè)備上不可用。
LAErrorBiometryNotAvailable NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryNotAvailable,
//身份驗證無法啟動蜕衡,因為生物識別沒有錄入信息壤短。
LAErrorBiometryNotEnrolled NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryNotEnrolled,
//身份驗證不成功,因為太多次的驗證失敗并且生物識別驗證是鎖定狀態(tài)。此時久脯,必須輸入密碼才能解鎖纳胧。例如LAPolicyDeviceOwnerAuthenticationWithBiometrics時候?qū)⒚艽a作為先決條件。
LAErrorBiometryLockout NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryLockout,
//身份驗證失敗帘撰。因為這需要顯示UI已禁止使用interactionNotAllowed屬性跑慕。 據(jù)說是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.首先引入指紋解鎖的庫文件
#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驗證" reply:^(BOOL success, NSError * _Nullable error) {
//注意iOS 11.3之后需要配置Info.plist權(quán)限才可以通過Face ID驗證哦!不然只能輸密碼啦...
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"驗證成功");
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"當(dāng)前軟件被掛起并取消了授權(quán) (如App進入了后臺等)");
NSLog(@"error-->%@",error);
});
}
}];
}
}
========
判斷設(shè)備是否支持TouchID 和 FaceID
-(void)justTouchIDFaceID{
// 檢測設(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(@"檢測設(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");
// 因為iPhoneX起始系統(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.");
}
}