iOS8:TouchID


引言

      在20139月,苹果推出了最新的iPhone与一系列硬件的改进。 iPhone 5S的最具创新性的特点是home键的指纹传感器,叫做触摸ID薄金属带。经过一年,Apple iOS 8引入了一个新的框架(Local Authentication),使开发人员能够使用TouchID

iOS8:TouchID_第1张图片

 Local Authentication framework提供了一些方法来提示用户进行身份验证。我们可以使用它作为登录应用程序,或使用它只是为了在一个应用程序保护敏感数据。在本教程中,我将解释可用的选项,哪些数据可以从设备得到的,而且我们还将构建一个示例应用程序。


 TouchID是指内置到iPhone5Shome键的指纹传感器。它被开放是使它更容易为用户进行身份验证。截至目前,它已被用于解锁iphone,并使在iTunes StoreApp Store的,和iBooks商店购买。

TouchID传感器可以扫描我们的手指。分辨率可以达到每英寸500像素,能够把每个指纹分成三类:拱,螺纹,或循环。该传感器的设计是真正的方便,你可以扫描你的手指在任何方向,无论原来的方向如何,它都会确定一个与任何现有的指纹相吻合的指纹印。


  苹果声称的指纹错误的可能性是50,000分之一,这比在猜测在14PIN码的错误的可能性10,000分之一要好得多。他们不提,有可能退回到使用的次针数,当你不能用你的指纹,例如:当你游泳的时候手指变皱指纹解锁就无法使用啦,但是幸运的是还有PIN码解锁。

  如果你打算使用TouchID,那么它很重要,你得考虑好方案。例如有时候PIN码作为验证不能真正的代表为是机主本人最好的主意就是用TouchID啦。


iOS8:TouchID_第2张图片

Local Authentication framework处理了所有验证用户的繁重。当TouchID起作用,重要的是要知道,它没有关于用户的任何详细信息,也没有数据从设备传送。而且,开发者可以使用该框架,来检查是否允许用户使用该应用程序。


API介绍

LocalAuthentication.framework提供了指纹验证的安全策略,使用方法如下.

 1). 导入头文件 Local Authentication Framework

#import <LocalAuthentication/LocalAuthentication.h>
 2).  创建一个 Local Authentication Context变量.

LAContext *myContext = [[LAContext alloc] init];

 3). 检查 Touch ID 有没有设置和能不能使用.

- (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError * __autoreleasing *)error;

4). 调用 Touch ID Authentication 方法.

- (void)evaluatePolicy:(LAPolicy)policy 
                    localizedReason:(NSString *)localizedReason 
                    reply:(void(^)(BOOL success, NSError *error))reply;
具体如下:

LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = <#String explaining why app needs authentication#>;
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
    [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
              localizedReason:myLocalizedReasonString
                        reply:^(BOOL success, NSError *error) {
                            if (success) {
                                // User authenticated successfully, take appropriate action
                            } else {
                                // User did not authenticate successfully, look at error and take appropriate action
                            }
                        }];
} else {
    // Could not evaluate policy; look at authError and present an appropriate message to user
}

所有的这些内容尽在ios8开始支持,因此如果你的应用需要支持低版本的设备,需要做分支处理.所以还要加一个判断,如下:

-(void)openTouchID{
    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1)
    {
        return;
    }
    LAContext *myContext = [[LAContext alloc] init];
    NSError *authError = nil;
    NSString *myLocalizedReasonString = @"通过指纹解锁app进入";
    
    if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
        [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
                  localizedReason:myLocalizedReasonString
                            reply:^(BOOL success, NSError *error) {
                                if (success) {
                                    dispatch_async(dispatch_get_main_queue(), ^{
                                        ((SPAppDelegate *)[[UIApplication sharedApplication] delegate])._ignoreNextApplicationDidBecomeActive=YES;
                                        [self dismissViewControllerAnimated:YES completion:nil];
                                    });
                                } else {
                                    dispatch_async(dispatch_get_main_queue(), ^{
                                        NSString *message = @"其他错误";
                                        if (error.code == kLAErrorUserFallback) {
                                            message = @"用户选择密码输入";
                                        }else if (error.code == kLAErrorUserCancel){
                                            message = @"用户取消验证";
                                        }else if (error.code == kLAErrorSystemCancel){
                                            message = @"系统取消验证";
                                        }
                                        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"错误"
                                                                                            message:message
                                                                                           delegate:self
                                                                                  cancelButtonTitle:@"OK"
                                                                                  otherButtonTitles:nil, nil];
                                        [alertView show];
                                    });
                                }
                            }];
    } else {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *message = @"未知错误";
            if (authError) {
                
                if (authError.code == kLAErrorPasscodeNotSet) {
                    //为设置密码与指纹
                    message = @"用户未设置密码";
                }else if(authError.code == kLAErrorTouchIDNotEnrolled){
                    //未设置指纹
                    message = @"用户未设置指纹";
                }else if(authError.code == kLAErrorTouchIDNotAvailable){
                    message = @"设备不支持指纹";
                }
            }

            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
                                                                message:authError.description
                                                               delegate:self
                                                      cancelButtonTitle:@"OK"
                                                      otherButtonTitles:nil, nil];
            [alertView show];
        });
    }
   
}


5). 调用 Touch ID Authentication 就这么简单,Build and Run

效果一:

iOS8:TouchID_第3张图片

效果二

iOS8:TouchID_第4张图片

LAContext 类是用来验证用户身份的组件.

方法

- (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError * __autoreleasing *)error;

用来判断用户是否可以使用指定策略的安全验证.

目前苹果仅提供指纹验证的策略(LAPolicyDeviceOwnerAuthenticationWithBiometrics).

用户用手机不支持指纹或用户未设置指纹时,此方法会返回NO,并在error参数中返回具体的错误信息.


当确定用户可以使用指纹识别后,调用方法

- (void)evaluatePolicy:(LAPolicy)policy
                          localizedReason:(NSString *)localizedReason
                                    reply:(void(^)(BOOL success, NSError *error))reply;

来请求指纹验证功能.识别为弹出指纹验证提示框.此方法需要提供3个参数.

policy为安全验证策略,目前只能使用LAPolicyDeviceOwnerAuthenticationWithBiometrics.

localizedReason,说明需要验证的原因,苹果的要求是此字段必须简明,且不可缺少.

replyblock代码.当用户操作指纹验证后回调此block.经测试当用户指纹验证失败后是不会回调的.只有用户验证成功,取消或点击使用密码按钮时才会回调.指纹验证成功后success返回YES,其他情况返回NO,并在error中附带错误信息.


所有的错误信息在LAError.h中定义.

LAErrorAuthenticationFailed 认证失败
LAErrorUserCancel用户点击取消按钮
LAErrorUserFallback用户点击Enter Password按钮
LAErrorSystemCancel系统取消了验证,比如令一个用户需要运行时
LAErrorPasscodeNotSet用户没有设置密码
LAErrorTouchIDNotAvailable设备不支持touch id
LAErrorTouchIDNotEnrolled设备没有录入指纹

你可以根据这些错误提示采取不同的策略.

源码优化:

上面TouchID Demo 基本完成,剩下的就是一些细节。当我们把触发TouchID 的方法放在applicationDidBecomeActive时会发现一个问题。

iOS8:TouchID_第5张图片

 如果在applicationDidBecomeActive中调用evaluatePolicy:localizedReason:reply弹出Touch ID验证alert的话, 如果用户解锁成功或者点击了Cancel, 那么就进入了死循环: cancel掉Touch ID的alert会触发applicationDidBecomeActive, 程序在applicationDidBecomeActive中弹出Touch ID, 用户点击Cancel...... 
所以考虑把Touch ID验证放在applicationWillEnterForeground中. 但问题来了, app第一次打开没有触发调用TouchID 方法的,或者如果另外一个app使用openURL方式跳到本app, 本app做一下处理后再跳回到跳到本程序的那个app. 这个场景下, 是不能弹出Touch ID的, 但是上面提到Touch ID是在applicationWillEnterForeground中调用的, 那时还尚未调用application:openURL:sourceApplication:annotation:, 程序不知道自己是正常启动还是被其他app使用openURL打开的, 怎么办?
  解决方法有两个:本Demo 采用第二种方法)
首先, 在application:openURL:sourceApplication:annotation:中设置标志位是必须的.
1. 如果本app做的处理不耗时的话, 例如只是保存个图片什么的, 耗时一般不会超过1秒, 可以考虑在applicationWillEnterForeground中等待一小段时间后判断是不是openURL启动的, 再弹出Touch ID.
2. 把Touch ID放到applicationDidBecomeActive, 设置标志位, 比如起名_ignoreNextApplicationDidBecomeActive. 在reply回调中, 判断用户是否点击了Cancel, 如果是的话, 将该标志位赋为YES. 下次进入applicationDidBecomeActive判断该标志位如果为YES, 将该标志位设为NO; 如果为NO, 则弹出Touch ID.


参考文档:

LocalAuthentication Framework Reference 

iOS Touch ID Authentication API Tutorial

点击下载源码


你可能感兴趣的:(iOS8:TouchID)