天天看点

iOS 关于指纹验证LocalAuthentication

iOS 关于指纹验证LocalAuthentication

IMG_0152.PNG

最近做项目版本更新有个需求是 3DTouch解锁功能, 由此原因接触 Apple的指纹解锁功能, 基本功能原先已经实现好了,发现了一个 Bug然后来优化一下,先扯会儿等下我会附上源代码, 其实在指纹解锁功能上 Apple已经帮我们封装好了, 我们需要写的代码其实并不多。

想更详细了解的可以直接参考Apple文档:

https://developer.apple.com/documentation/localauthentication

。不过我个人更推荐的学习方法是在学习一个新知识点时,最好先参考一篇觉得写得不错,自己更容易理解的Blog看看作者的理解分析,以及有源代码 Dome附上更佳!!! 因为对于一个新的知识点类库, 会有很多我们没接触过的类,以及一些API的调用等。我们直接一头雾水的去看Apple文档可能效果不会最佳。

好了上面扯的一大堆废话,现在该步入正题了。

我会直接参考着 Apple文档介绍做指纹解锁功能用到的类以及 API的调用等。

一.LAContext

顾名思义此类是关于锁认证凭证的一个上下文类。我们我们直接从此类入手, 引用官方文档概念说明:认证上下文用于评估认证策略,允许应用程序请求用户使用诸​​如使用 Touch ID注册的指纹等个人信息进行身份验证。 其是管理认证凭证的一个核心类 文档说明中还有一条重要的信息SDK要求: iOS 8.0以上版本、只有iOS 8.0以上版本才可以正常使用指纹解锁功能! 然后我们来看一下此类包含的属性以及API。从 Xcode进入官方声明的的LAContext文件可见其内容并不多,只有290行代码。分别罗列其公共的属性:

@property (nonatomic, nullable, copy) NSString localizedFallbackTitle;//我们可以先看一下文档上的注释, 其表示的是指纹解锁弹框的回退按钮标题,/// @discussion Allows fallback button title customization. A default title "Enter Password" is used whenthis property is left nil. If set to empty string, the button will be hidden.从文档注释上我们还可以看出这个按钮标题默认是“输入密码”,如果我们将此属性设置为nil 此按钮会隐藏掉。

@property (nonatomic, nullable, copy) NSString localizedCancelTitle 取消按钮标题。 默认值是 Cancel 、 我们可以自定义设置 按钮Title 也可以设置为 nil 或者其他字符串。

@property (nonatomic, nullable) NSNumber maxBiometryFailures NS_DEPRECATED_IOS(8_3, 9_0) __WATCHOS_UNAVAILABLE __TVOS_UNAVAILABLE; //// 此属性是设置允许验证失败最大次数、 默认如果不设置的话 是3次之后验证失败、 文档注释有个警告说明 是 /// @warning Please note that setting this property with high values does not prevent biometry lockout after 5 设置了属性之后即时认证失败次数超过了5次、也会直接认证失败。 在Apple文档上 看到此属性已经被标记为 弃用 ,所以我们最好直接使用默认的 3次即可!

touchIDAuthenticationAllowableReuseDuration

允许使用Touch ID身份验证的持续时间。

继续到相关API:

- canEvaluatePolicy:error:

预先验证身份验证策略,以查看身份验证是否可以成功。 // 我们可以直接使用此方法来判断此设备是否支持使用指纹解锁。返回值是个BOOL

- evaluatePolicy:localizedReason:reply:

//核心方法。直接使用 ALContext实例调用此方法,直接弹出指纹认证框。详细解释一下里面的三个参数

@param->policy 其是一个枚举。具体看

https://developer.apple.com/documentation/localauthentication/lapolicy?language=objc

介绍、 我们直接使用枚举第一个参数。

@param->localizedReason 类型是NSString、 我们可以提供一段字符串,其会展示在弹框中间。如"Wechat请你您验证指纹"等、

@param->reply 此参数是一个 返回值为空,第一个参数是BOOL 表示验证执行结果、第二个参数是NSError 表示执行错误原因 的回调block。 我们可以在调用此方法时把具体回调执行步骤 根据 参数 执行我们想要执行的操作。然后回调失败具体是一个 枚举 LAError 我们可以参考

https://developer.apple.com/documentation/localauthentication/laerror?language=objc

里面有不同的失败原因。

- invalidate

使验证上下文无效。// 在验证期间调用此方法 相当于是此次验证失败。 失败的原因类似 系统取消等。

还有剩下几个API 由于开发指纹解锁 仅需要 用到这两个即可!写的太多感觉有点啰嗦。 所以暂时先不对其介绍。目前我们只要搞懂这几个属性和API即可轻松完成指纹解锁的功能。因为具体的弹框指纹验证等主要的功能 Apple已经帮我们封装好了。 只要我们调用 刚刚介绍的第二个API 即可 一步完成指纹 验证。 是不是超级超级简单!!!!!* 讲到这里大家应该对指纹解锁有了一个大概的了解了**。在此附上一段简短的实现代码供大家参考。

指纹解锁实现参考:

LAContext context = [[LAContext alloc] init];

NSError error = nil;

BOOL canUse = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];

if(canUse) {

[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"Jersey请您验证指纹"reply:^(BOOL success, NSError error) {

NSLog(@"evaluatePolicy Biometrics %@",error);

if (success) {

//注意我们在执行回调的时候必须使用异步、否则会卡顿。影响体验*

dispatch_async(dispatch_get_main_queue(), ^{

reply(YES, error);

});

}

else {

switch (error.code) {

case LAErrorTouchIDLockout:

{

NSLog(@"验证失败,由于认证次数超过指定次数。账户可能会被锁定");

// 我再这里调用封装好的方法,让用户先去验证一次手机密码,成功之后才能继续使用指纹验证。

break;

case LAErrorUserCancel:

NSLog(@"验证失败,用户点击取消");

default:

reply(NO, [NSError errorWithDomain:@"Touch ID Failed." code:TouchIDErrorFailed userInfo:nil]);

}];

只需调用此方法即可实现弹框提示用户进行指纹验证。感谢Apple给力的封装! 但是不要高兴的太早,目前我正在使用此API出现的问题就是,当用户快速点击两次指纹验证按钮时, 此API会直接调用两次, 然后直接出现的问题就是第一次弹框出现后消失,然后继续弹出一个验证的框。 然后我在API的错误回调里面执行了一个弹框提示的方法、此时问题就出来了。不仅弹两次框,还提示一个验证失败的指示器。看着有点不舒服。但是由于此功能Apple已经封装完好, 并没有把弹出的框属性直接暴露出来、 我目前还找不到合适的办法去检测此ALContext是否正在处于验证状态。 所以只能想了其他方法先把目前遇到的问题解决了。

方法一:延迟当前按钮相应弹框事件的时间。 这样一来不管用户点击多少次最终只会执行一次点击的事件,我们可以设一个延长时间,每次点击这个按钮的时候会把上次点击发送的事件取消掉。直到我们设置的延时后才会去执行一次这个事件 附上代码

- (void)clickfingerprintBtnAction:(UIButton *)btn{
// 在0.2秒时间间隔内多次点击只响应一次点击事件, todoSomething就是我们具体要实现的方法
[[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(todoSomething:) object:btn];
[self performSelector:@selector(todoSomething:) withObject:btn afterDelay:0.2f];
}

-(void)todoSomething:(UIButton *)btn{

//这里直接写我们具体的指纹认证实现即可

}
           

此方法的也可以有效的防止连续弹框、因为不管点击多少次最终只会执行一次弹框认证的事件。但是缺点就是每次点击完要延迟个0.2S才会执行指纹弹框认证。

方法二: 在类中创建一个标识符、用来表示当前是否正在验证。 我们在调用弹框操作前 根据此属性去判断弹框是否存在。 如存在则不去执行直接 return即可。 然后我们在每次执行方法前 将 此属性 改为 YES、 在方法的回调 将 此属性 改为 NO即可。

希望此篇文章对您有所帮助,如有不对的地方,希望大家能留言指出纠正。谢谢!!!

学习的路上, 与君共勉!!!

在文章结尾给大家附上一篇已经写好的Dome供大家继续参考 ------>

https://github.com/ClearLoveLee/LM_TouchID

继续阅读