iOS8:TouchID

引言

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


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


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

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


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

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



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


API介绍

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

 1). 导入头文件 Local Authentication Framework

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #import <LocalAuthentication/LocalAuthentication.h>  
 2).  创建一个 Local Authentication Context变量.

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. LAContext *myContext = [[LAContext alloc] init];  

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

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. - (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError * __autoreleasing *)error;  

4). 调用 Touch ID Authentication 方法.

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. - (void)evaluatePolicy:(LAPolicy)policy   
  2.                     localizedReason:(NSString *)localizedReason   
  3.                     reply:(void(^)(BOOL success, NSError *error))reply;  
具体如下:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. LAContext *myContext = [[LAContext alloc] init];  
  2. NSError *authError = nil;  
  3. NSString *myLocalizedReasonString = <#String explaining why app needs authentication#>;  
  4. if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {  
  5.     [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics  
  6.               localizedReason:myLocalizedReasonString  
  7.                         reply:^(BOOL success, NSError *error) {  
  8.                             if (success) {  
  9.                                 // User authenticated successfully, take appropriate action  
  10.                             } else {  
  11.                                 // User did not authenticate successfully, look at error and take appropriate action  
  12.                             }  
  13.                         }];  
  14. } else {  
  15.     // Could not evaluate policy; look at authError and present an appropriate message to user  
  16. }  

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

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. -(void)openTouchID{  
  2.     if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1)  
  3.     {  
  4.         return;  
  5.     }  
  6.     LAContext *myContext = [[LAContext alloc] init];  
  7.     NSError *authError = nil;  
  8.     NSString *myLocalizedReasonString = @"通过指纹解锁app进入";  
  9.       
  10.     if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {  
  11.         [myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics  
  12.                   localizedReason:myLocalizedReasonString  
  13.                             reply:^(BOOL success, NSError *error) {  
  14.                                 if (success) {  
  15.                                     dispatch_async(dispatch_get_main_queue(), ^{  
  16.                                         ((SPAppDelegate *)[[UIApplication sharedApplication] delegate])._ignoreNextApplicationDidBecomeActive=YES;  
  17.                                         [self dismissViewControllerAnimated:YES completion:nil];  
  18.                                     });  
  19.                                 } else {  
  20.                                     dispatch_async(dispatch_get_main_queue(), ^{  
  21.                                         NSString *message = @"其他错误";  
  22.                                         if (error.code == kLAErrorUserFallback) {  
  23.                                             message = @"用户选择密码输入";  
  24.                                         }else if (error.code == kLAErrorUserCancel){  
  25.                                             message = @"用户取消验证";  
  26.                                         }else if (error.code == kLAErrorSystemCancel){  
  27.                                             message = @"系统取消验证";  
  28.                                         }  
  29.                                         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"错误"  
  30.                                                                                             message:message  
  31.                                                                                            delegate:self  
  32.                                                                                   cancelButtonTitle:@"OK"  
  33.                                                                                   otherButtonTitles:nil, nil];  
  34.                                         [alertView show];  
  35.                                     });  
  36.                                 }  
  37.                             }];  
  38.     } else {  
  39.         dispatch_async(dispatch_get_main_queue(), ^{  
  40.             NSString *message = @"未知错误";  
  41.             if (authError) {  
  42.                   
  43.                 if (authError.code == kLAErrorPasscodeNotSet) {  
  44.                     //为设置密码与指纹  
  45.                     message = @"用户未设置密码";  
  46.                 }else if(authError.code == kLAErrorTouchIDNotEnrolled){  
  47.                     //未设置指纹  
  48.                     message = @"用户未设置指纹";  
  49.                 }else if(authError.code == kLAErrorTouchIDNotAvailable){  
  50.                     message = @"设备不支持指纹";  
  51.                 }  
  52.             }  
  53.   
  54.             UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"  
  55.                                                                 message:authError.description  
  56.                                                                delegate:self  
  57.                                                       cancelButtonTitle:@"OK"  
  58.                                                       otherButtonTitles:nil, nil];  
  59.             [alertView show];  
  60.         });  
  61.     }  
  62.      
  63. }  


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

效果一:

效果二


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

方法

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. - (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError * __autoreleasing *)error;  

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

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

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


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

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. - (void)evaluatePolicy:(LAPolicy)policy  
  2.                           localizedReason:(NSString *)localizedReason  
  3.                                     reply:(void(^)(BOOL success, NSError *error))reply;  

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

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

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

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


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

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. LAErrorAuthenticationFailed 认证失败  
  2. LAErrorUserCancel用户点击取消按钮  
  3. LAErrorUserFallback用户点击Enter Password按钮  
  4. LAErrorSystemCancel系统取消了验证,比如令一个用户需要运行时  
  5. LAErrorPasscodeNotSet用户没有设置密码  
  6. LAErrorTouchIDNotAvailable设备不支持touch id  
  7. LAErrorTouchIDNotEnrolled设备没有录入指纹  

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

源码优化:

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


 如果在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

点击下载源码


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值