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

Local Authentication framework提供了一些方法来提示用户进行身份验证。我们可以使用它作为登录应用程序,或使用它只是为了在一个应用程序保护敏感数据。在本教程中,我将解释可用的选项,哪些数据可以从设备得到的,而且我们还将构建一个示例应用程序。
TouchID是指内置到iPhone5S的home键的指纹传感器。它被开放是使它更容易为用户进行身份验证。截至目前,它已被用于解锁iphone,并使在iTunes Store,App Store的,和iBooks商店购买。
TouchID传感器可以扫描我们的手指。分辨率可以达到每英寸500像素,能够把每个指纹分成三类:拱,螺纹,或循环。该传感器的设计是真正的方便,你可以扫描你的手指在任何方向,无论原来的方向如何,它都会确定一个与任何现有的指纹相吻合的指纹印。
苹果声称的指纹错误的可能性是50,000分之一,这比在猜测在1一4位PIN码的错误的可能性10,000分之一要好得多。他们不提,有可能退回到使用的次针数,当你不能用你的指纹,例如:当你游泳的时候手指变皱指纹解锁就无法使用啦,但是幸运的是还有PIN码解锁。
如果你打算使用TouchID,那么它很重要,你得考虑好方案。例如有时候PIN码作为验证不能真正的代表为是机主本人最好的主意就是用TouchID啦。

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
效果一:

效果二

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,说明需要验证的原因,苹果的要求是此字段必须简明,且不可缺少.
reply为block代码.当用户操作指纹验证后回调此block.经测试当用户指纹验证失败后是不会回调的.只有用户验证成功,取消或点击使用密码按钮时才会回调.指纹验证成功后success返回YES,其他情况返回NO,并在error中附带错误信息.
所有的错误信息在LAError.h中定义.
- LAErrorAuthenticationFailed 认证失败
- LAErrorUserCancel用户点击取消按钮
- LAErrorUserFallback用户点击Enter Password按钮
- LAErrorSystemCancel系统取消了验证,比如令一个用户需要运行时
- LAErrorPasscodeNotSet用户没有设置密码
- LAErrorTouchIDNotAvailable设备不支持touch id
- 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
点击下载源码