【iOS】指纹(面容)支付基本逻辑和适配

  • 时间:2018-08-16 23:08 作者:x_code 来源:x_code 阅读:909
  • 扫一扫,手机访问
摘要:在这边提供少量指纹和面容支付的基本思路,差异以及所遇到的坑。一、支付逻辑基本思路我们重点是考虑如何保证支付的安全,首先一定不能本地存入使用户的支付密码,这样在人行(中国人民银行)来检查的时候是行不通的,而且直接存密码在任何时候都是下下策。我们应该考虑在指纹验证通过后,如何和服务端进行安全交互:1、首先

在这边提供少量指纹和面容支付的基本思路,差异以及所遇到的坑。

一、支付逻辑基本思路

我们重点是考虑如何保证支付的安全,首先一定不能本地存入使用户的支付密码,这样在人行(中国人民银行)来检查的时候是行不通的,而且直接存密码在任何时候都是下下策。
我们应该考虑在指纹验证通过后,如何和服务端进行安全交互:
1、首先指纹或者者面容通过后,我们需要和服务端进行安全环境校验,这个目的是保证当前的环境是安全的。可参考的方式有两种,第一种是使用RSA加密,公钥加密私钥解密。第二种是AES加密,用规定的key进行加解密。
2、安全环境校验通过后,再将所需的字段拼接加密后传给服务端进行校验,校验通过就可支付。这里所需的字段有一点,就是肯定要保证唯一性,可以是设施id,使用户id组合成的唯一id,相似于token。

二、适配面容支付

iPhoneX出了Face ID,因而我们也需要对Face ID进行适配(尽管我觉得不太安全,没有指纹有安全感)。
1、在系统API调使用方面,其实是一样的,只是需要区分下何时是指纹何时是面容,以便进行图片、文字的更换,系统API提供了一个LABiometryType枚举进行类型判断,代码如下:

  LAContext *context  = [[LAContext alloc]init];  NSError *authError = nil;// MARK: 判断设施能否支持指纹识别if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]){    NSString *myLocalizedReasonString;    //系统给的系统判断API    if (@available(iOS 11.0, *)) {        if(context.biometryType == LABiometryTypeTouchID) {            myLocalizedReasonString = @"请按Home键验证指纹";        }else if (context.biometryType == LABiometryTypeFaceID){            myLocalizedReasonString = @"请验证面容 ";        }else{            myLocalizedReasonString = @"请按Home键验证指纹";        }    }  //iOS 11以前没有面容    else{        myLocalizedReasonString = @"请按Home键验证指纹";    };}

这里需要注意的是肯定要先使用 if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError])进行判断,而后再使用LABiometryType取出验证类型,这在很多文章里都没有提过,也是我在开发过程中遇到的问题。还有一点就是系统提供了一个写法来判断方法支持最低的iOS系统: if (@available(iOS 11.0, )) {},以后可以不使用网上的判断系统的方法了。

三、LAError枚举值说明

iOS 11新添加了3个枚举,其实都是和以前的一样,只不过换了个名字:

LAErrorAuthenticationFailed, // 验证信息出错,这个时候会弹出localizedFallbackTitle的按钮  LAErrorUserCancel // 使用户取消验证LAErrorUserFallback // 使用户点击了手动输入密码的按钮LAErrorSystemCancel // 被系统取消 LAErrorPasscodeNotSet // 使用户没有设置密码(六位数字或者者四位数字那个)LAErrorTouchIDNotAvailable // 使用户设施不支持Touch ID LAErrorTouchIDNotEnrolled // 使用户没有录入Touch IDLAErrorTouchIDLockout // 使用户错误次数被锁住了,需要解锁LAErrorAppCancel // 在验证中被其余app终止LAErrorInvalidContext // 这个应该是LAContext本身出错了,我还没遇到过//这个没遇到过,预计没使用了,枚举值都变成-1004了,说明被舍弃了LAErrorNotInteractive //下面是iOS 11新添加的LAErrorBiometryNotAvailable //和LAErrorTouchIDNotAvailable一样枚举值都是-6LAErrorBiometryNotEnrolled //和LAErrorTouchIDNotEnrolled一样枚举值都是-7LAErrorBiometryLockout //和LAErrorTouchIDLockout一样枚举值都是-8

四、LAPolicy枚举值说明

LAPolicy一共有两个LAPolicyDeviceOwnerAuthenticationWithBiometrics和LAPolicyDeviceOwnerAuthentication,区别是:
1、LAPolicyDeviceOwnerAuthentication是iOS 9之后的;
2、LAPolicyDeviceOwnerAuthentication是在指纹面容验证失败后(5次)第6次弹出锁屏密码验证,假如验证成功了即可以认定指纹或者者面容成功了。
3、LAPolicyDeviceOwnerAuthenticationWithBiometrics则是失败5次后,第6次指纹或者者面容就被锁定了,我们需要在第6次解锁指纹或者者面容,代码如下:

case LAErrorTouchIDLockout:{             dispatch_async(dispatch_get_main_queue(), ^{                [context evaluatePolicy:kLAPolicyDeviceOwnerAuthentication localizedReason:@"验证手机锁屏密码,解锁指纹" reply:^(BOOL success, NSError * _Nullable error){                    if (success) {                       //重新进行指纹校验方法调使用                    }                }];            });                        break;        }

需要注意的是使用swich遍历LAError的时候,操作需要在主线程进行。

五、指纹验证示例整段代码

#pragma mark - 验证指纹- (void)loadAuthentication{    // 这个属性是设置指纹输入失败之后的弹出框的选项    LAContext *context  = [[LAContext alloc]init];    context.localizedFallbackTitle = @"输入密码";    NSError *authError = nil;    // MARK: 判断设施能否支持指纹识别       if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]){    NSString *myLocalizedReasonString;    if (@available(iOS 11.0, *)) {        if(context.biometryType == LABiometryTypeTouchID) {            myLocalizedReasonString = @"请按Home键验证指纹";        }else if (context.biometryType == LABiometryTypeFaceID){            myLocalizedReasonString = @" 请验证面容ID";        }else{            myLocalizedReasonString = @"请按Home键验证指纹";        }    }    else{        myLocalizedReasonString = @"请按Home键验证指纹";    };    [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:myLocalizedReasonString reply:^(BOOL success, NSError * _Nullable error) {                if(success){            //在主线程进行            dispatch_async(dispatch_get_main_queue(), ^{                //认证成功                //进行支付            });                    }else{            dispatch_async(dispatch_get_main_queue(), ^{                            });            switch (error.code){                case LAErrorAuthenticationFailed:{                    // -1 连续三次指纹识别错误                    dispatch_async(dispatch_get_main_queue(), ^{                       //认证失败,请输入支付密码支付                    });                    break;                }                                    case LAErrorUserFallback:{                    // -3 使用户选择其余验证方式                    (点击了 context.localizedFallbackTitle = @"输入密码"这里的响应)                    //主线程                    dispatch_async(dispatch_get_main_queue(), ^{                                            });                    break;                }                                        // Authentication could not start, because passcode is not set on the device.                    // -5 设施系统未设置密码                    //没有面容ID权限(-6)                case LAErrorTouchIDNotAvailable:{                    dispatch_async(dispatch_get_main_queue(), ^{                       //引导使用户跳转到设置去开启                                            });                    break;                }                //iPhone没设置密码                  case LAErrorPasscodeNotSet :{                    dispatch_async(dispatch_get_main_queue(), ^{                       //引导使用户跳转到设置去开启                                            });                    break;                }                  //iPhone没录入指纹                 case LAErrorTouchIDNotEnrolled:{                    dispatch_async(dispatch_get_main_queue(), ^{                       //引导使用户跳转到设置去录入                                            });                    break;                }              //使用户连续屡次进行Touch ID验证失败,Touch ID被锁,需要使用户输入密码解锁,先Touch ID验证密码                case LAErrorTouchIDLockout:{                    // -8 连续五次指纹识别错误,TouchID功能被锁定,下一次需要输入系统密码                    dispatch_async(dispatch_get_main_queue(), ^{                        [context evaluatePolicy:kLAPolicyDeviceOwnerAuthentication localizedReason:@"验证手机锁屏密码,解锁指纹" reply:^(BOOL success, NSError * _Nullable error){                            if (success) {                                [self loadAuthentication];                            }                        }];                    });                    break;                }                                    default:{                                      break;                }            }        }    }];}else{    switch (authError.code){        //没有面容ID权限(-6)        case LAErrorTouchIDNotAvailable:{            dispatch_async(dispatch_get_main_queue(), ^{                //引导使用户跳转到设置去开启                           });            break;        }        case LAErrorAuthenticationFailed:{            // -1 连续三次指纹识别错误            dispatch_async(dispatch_get_main_queue(), ^{                               //认证失败,请输入支付密码支付            });            break;        }                    case LAErrorPasscodeNotSet :{            dispatch_async(dispatch_get_main_queue(), ^{                //引导使用户跳转到设置去开启            });            break;        }        case LAErrorTouchIDNotEnrolled:{            dispatch_async(dispatch_get_main_queue(), ^{                //引导使用户跳转到设置去开启            });            break;        }                    case LAErrorTouchIDLockout:{            dispatch_async(dispatch_get_main_queue(), ^{                [context evaluatePolicy:kLAPolicyDeviceOwnerAuthentication localizedReason:@"验证手机锁屏密码,解锁指纹" reply:^(BOOL success, NSError * _Nullable error){                    if (success) {                        [self loadAuthentication];                    }                }];            });                        break;        }                default:{            dispatch_async(dispatch_get_main_queue(), ^{                if (@available(iOS 11.0, *)) {                    if(context.biometryType == LABiometryTypeTouchID) {                       //设施不支持Touch ID                    }else if (self.myContext.biometryType == LABiometryTypeFaceID){                        //设施不支持面容 ID                    }else{                      //设施不支持Touch ID                    }                }else{                    //设施不支持Touch ID                }            });            break;        }      }    }  }

五、总结

具体的指纹支付逻辑,加密方式,还是应该和服务端以及安卓一起探讨决定。其余就是做好异常解决,保证代码安全。
目前我还遇到了一个奇怪的bug,就是iOS 11.0系统,使用户录入了指纹,但是没有将指纹或者者密码使用于锁屏解锁,就会每次都跳出LAErrorTouchIDLockout这个错误。试了一下,微信和支付宝一样的,也就是系统bug,其余系统正常。后续假如有其余的我还会补充。

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】Fortigate飞塔防火墙如何开启DNS转发/DNS代理(2025-10-14 23:58)
【系统环境|】有了它,再也不用担心电脑弹窗广告和病毒啦!(2025-10-14 23:57)
【系统环境|】如何关闭恼人的电脑弹窗广告?2招搞定(2025-10-14 23:55)
【系统环境|】实用软件推荐:电脑广告弹窗多?用他,都给你屏蔽掉!(2025-10-14 23:55)
【系统环境|】Nginx篇01——基本安装配置和静态页面设置(2025-10-14 23:54)
【系统环境|】Linux端口开放,查看,删除,防火墙(2025-10-14 23:53)
【系统环境|】安全HTTP头部配置: 基于CSP与HSTS的Web安全策略(2025-10-14 23:52)
【系统环境|】老K:做私域过1000万的赛道全部都聚焦在女性身上!(2025-10-14 23:51)
【系统环境|】JavaScript跨域问题: 如何解决跨域访问和资源共享的安全策略(2025-10-14 23:51)
【系统环境|】家庭七级财务防火墙(2025-10-14 23:50)
手机二维码手机访问领取大礼包
返回顶部