TouchID 登陸

點擊這里:KeyChain and TouchID Demo

首先需要引入一個庫#import <LocalAuthentication/LAContext.h>,官方的一個用于TouchID安全驗證登陸的Framework,首先需要驗證是否支持TouchID登陸:

// 判斷是否支持TouchID登陸
- (BOOL)canEvaluatePolicy
{
    LAContext *context = [[LAContext alloc] init];
    NSError *error;
    return [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];
}

如果不支持的話,就需要走自己APP中得密碼驗證方法來進(jìn)行驗證登陸;
如果支持的話,就調(diào)起TouchID驗證的頁面:

- (void)evaluatePolicy
{
    LAContext *context = [[LAContext alloc] init];
    [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"使用TouchID進(jìn)入APP首頁" reply:^(BOOL success, NSError * _Nullable error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (success) {
                // ...
            }
            else {
                // ...
            }
        });
    }];
}

注意

reply這個block中得代碼是在異步線程中執(zhí)行的,如果有需要的話,必須得拋到主線程中去執(zhí)行一些東西。

TouchID的失敗次數(shù)是有限制的,從開始算,如果失敗了三次,系統(tǒng)就會自動的退出TouchID的驗證界面,并在replyblock中返回失敗的信息,這時還可以調(diào)起TouchID的驗證,此時如果失敗兩次即會退出驗證界面。
在這種情況下,如果還想用TouchID驗證,則必須輸入手機的登陸密碼才能繼續(xù)驗證。
需要注意的是,這個失敗的次數(shù)在iOS設(shè)備中所有的APP是累加起來的。

KeyChain

keychain是作為蘋果中對于數(shù)據(jù)安全存儲的一個地方,類似于NSUserDefaults,但又不同于NSUserDefaults。

對于keychain來說,需要注意的方法有以下四個:

  • SecItemAdd
  • SecItemUpdate
  • SecItemCopyMatching
  • SecItemDelete

注意

在使用的時候一定要注意KeyChain操作的返回值。

KeyChain操作中得一些參數(shù)的設(shè)定(一些相關(guān)參數(shù)的說明):

- (NSMutableDictionary *)getKeychainQueryWithService:(NSString *)service
{
    NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                (__bridge id)kSecClassGenericPassword, (__bridge id)kSecClass,
                service, (__bridge id)kSecAttrService,
                service, (__bridge id)kSecAttrAccount,
                (__bridge id)kSecAttrAccessibleAfterFirstUnlock, (__bridge id)kSecAttrAccessible,
            nil];
    if (self.accessGroupName != nil) {
        [query setObject:self.accessGroupName forKey:(__bridge id)kSecAttrAccessGroup];
    }
    return query;
}

SecItemAdd

用于將個人數(shù)據(jù)條目保存到keychain中。

  • 方法原型:OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * result);
    • attributes : 添加屬性的設(shè)置。
    • result : 可以用與獲取返回值,&res
- (OSStatus)saveObject:(id)object forService:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQueryWithService:service];
    // 需要檢查數(shù)據(jù)的存在性,如果存在的話,就用SecItemUpdate更新,否則就添加
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:object] forKey:(__bridge id)kSecValueData];
    return SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
}

SecItemUpdate

用于更新KeyChain中保存的數(shù)據(jù)。

  • 方法原型:OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);
    • query : 查找屬性的設(shè)置
    • attributesToUpdate : 要更新的數(shù)據(jù)
- (OSStatus)updateService:(NSString *)service withObject:(id)object
{
    NSDictionary *keychainQuery = [self getKeychainQueryWithService:service];
    NSDictionary *changes = @{
                              (__bridge id)kSecValueData : [NSKeyedArchiver archivedDataWithRootObject:object]
                              };
    return SecItemUpdate((__bridge CFDictionaryRef)keychainQuery, (__bridge CFDictionaryRef)changes);
}

SecItemCopyMatching

用于獲取保存在KeyChain中得數(shù)據(jù)。

  • 方法原型:OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * result);
    • query : 保存在KeyChain中得數(shù)據(jù)信息。
    • result : 從KeyChain中取得的數(shù)據(jù)。
- (id)loadObjectForService:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQueryWithService:service];
    [keychainQuery setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
    [keychainQuery setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
    CFDataRef dataRef = NULL;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&dataRef);
    id results = nil;
    if (status == errSecSuccess) {
        @try {
            results = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)dataRef];
        }
        @catch (NSException *exception) {
            NSLog(@"%@", exception);
        }
        @finally {
            NSLog(@"finally");
        }
    } 
    if (dataRef) {
        CFRelease(dataRef);
    }
    return results;
}

SecItemDelete

用于刪除保存在KeyChain中得數(shù)據(jù)。

  • 方法原型:OSStatus SecItemDelete(CFDictionaryRef query)
    • query:要刪除的數(shù)據(jù)的信息。
- (void)delete:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQueryWithService:service];
    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
}
TIDLogin

附:

OSStatus狀態(tài)碼

CF_ENUM(OSStatus)
{
    errSecSuccess                               = 0,       /* No error. */
    errSecUnimplemented                         = -4,      /* Function or operation not implemented. */
    errSecIO                                    = -36,     /*I/O error (bummers)*/
    errSecOpWr                                  = -49,     /*file already open with with write permission*/
    errSecParam                                 = -50,     /* One or more parameters passed to a function where not valid. */
    errSecAllocate                              = -108,    /* Failed to allocate memory. */
    errSecUserCanceled                          = -128,    /* User canceled the operation. */
    errSecBadReq                                = -909,    /* Bad parameter or invalid state for operation. */
    errSecInternalComponent                     = -2070,
    errSecNotAvailable                          = -25291,  /* No keychain is available. You may need to restart your computer. */
    errSecDuplicateItem                         = -25299,  /* The specified item already exists in the keychain. */
    errSecItemNotFound                          = -25300,  /* The specified item could not be found in the keychain. */
    errSecInteractionNotAllowed                 = -25308,  /* User interaction is not allowed. */
    errSecDecode                                = -26275,  /* Unable to decode the provided data. */
    errSecAuthFailed                            = -25293,  /* The user name or passphrase you entered is not correct. */
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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