iOS TouchID验证和Keychain结合使用

来源:互联网 发布:php数组遍历 编辑:程序博客网 时间:2024/06/07 00:25

1.TouchID的简单实现

首先先导入LocalAuthentication/LocalAuthentication.h头文件
使用TouchID前先检测TouchID是否可用,然后再调用

LAContext *context = [[LAContext alloc] init];BOOL success = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil];if(success){    NSLog(@"can use");}else{    NSLog(@"can`t user ");}
//在验证TouchID可用的情况下使用LAContext *context = [[LAContext alloc] init];context.localizedFallbackTitle = @"自定义标题";[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"为什么使用TouchID写这里" reply:^(BOOL success, NSError * _Nullable error) {    if(success){        //指纹验证成功    }else{        switch (error.code) {             case LAErrorUserFallback:{                NSLog(@"用户选择输入密码");                break;             }            case LAErrorAuthenticationFailed:{                NSLog(@"验证失败");                break;            }            case LAErrorUserCancel:{                NSLog(@"用户取消");                break;            }            case LAErrorSystemCancel:{                NSLog(@"系统取消");                break;            }            //以下三种情况如果提前检测TouchID是否可用就不会出现            case LAErrorPasscodeNotSet:{                break;            }            case LAErrorTouchIDNotAvailable:{                break;            }            case LAErrorTouchIDNotEnrolled:{                break;            }            default:               break;            }        }}];

这里写图片描述
这里写图片描述

2.Keychain简单使用

Keychain大体的保存使用流程如下图
这里写图片描述
下面是钥匙串的增删改查

//要像是串中增加一条/* kSecClass                   //类型 kSecAttrGeneric             //作为唯一标识 kSecAttrService             //所具有的服务 kSecAttrAccount             //用户名 kSecValueData               //保存密码对应的key kSecAttrModificationDate    //修改日期 */NSDictionary *attributes = @{(id)kSecClass: (id)kSecClassGenericPassword,                             (id)kSecAttrGeneric:[NSBundle mainBundle].bundleIdentifier,                             (id)kSecAttrService: @"SampleService",                             (id)kSecAttrAccount:userName,                             (id)kSecValueData:[password dataUsingEncoding:NSUTF8StringEncoding],                             (id)kSecAttrModificationDate:[NSDate date],                             };OSStatus status =  SecItemAdd((__bridge CFDictionaryRef)attributes, nil);if(status == errSecSuccess){    return YES;}else{    NSLog(@"%@",[self keychainErrorToString:status]);}//修改NSDictionary *attribute = @{(id)kSecClass: (id)kSecClassGenericPassword,                            (id)kSecAttrGeneric:[NSBundle mainBundle].bundleIdentifier,                            (id)kSecAttrService: @"SampleService",                            (id)kSecAttrAccount:userName,                            };NSDictionary *changeDic = @{(id)kSecValueData:[password dataUsingEncoding:NSUTF8StringEncoding],                            (id)kSecAttrModificationDate:[NSDate date]                            };OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)attribute, (__bridge CFDictionaryRef)changeDic);if(status == errSecSuccess){    return YES;}else{    NSLog(@"%@",[self keychainErrorToString:status]);}//查询NSDictionary *attributes = @{(id)kSecClass: (id)kSecClassGenericPassword,                             (id)kSecAttrGeneric:[NSBundle mainBundle].bundleIdentifier,                             (id)kSecAttrAccount:userName,                             (id)kSecAttrService: @"SampleService",                             (id)kSecReturnData: @YES,                             (id)kSecReturnAttributes:@YES,                             (id)kSecMatchLimit:(id)kSecMatchLimitOne,                            };CFMutableDictionaryRef outDictionary = nil;OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)attributes, (CFTypeRef *)&outDictionary);if(status == errSecSuccess){    NSDictionary *result = (__bridge_transfer NSDictionary *)outDictionary;    NSData *passWordData = result[(id)kSecValueData];    if(passWordData){        return [[NSString alloc] initWithData:passWordData encoding:NSUTF8StringEncoding];    }}else{    NSLog(@"%@",[self keychainErrorToString:status]);}//删除NSDictionary *attributes = @{(id)kSecClass: (id)kSecClassGenericPassword,                        (id)kSecAttrGeneric:[NSBundle mainBundle].bundleIdentifier,                        (id)kSecAttrService: @"SampleService",                        (id)kSecAttrAccount:userName                        };OSStatus status = SecItemDelete((__bridge CFDictionaryRef)attributes);if(status == errSecSuccess){    return YES;}else{    NSLog(@"%@",[self keychainErrorToString:status]);}

看好多APP都有指纹登录,长时间没有登录的话指纹登录会失效
我想了一下实现思路
1. APP内部有一个指纹登录开关,打开开关
2. 将账号和密码存储到钥匙串,将当前账号存储到沙盒中
3. 下次登录时根据沙盒存储的账号到钥匙串中查询密码和修改时间
4. 如果钥匙串的修改时间和当前时间的差值不超过你的预设范围就可以用钥匙串中密码登录,如果超除了预设范围就需要密码输入,登录成功后更新钥匙串的密码和修改时间
5. 如果钥匙串中数据的密码错误(可能在其他机器中修改过密码等),则需要输入密码,登陆成功后更新钥匙串
6. 如果关闭指纹登录则需要将钥匙串删除

TouchID和Keychain的简单使用Demo地址

原创粉丝点击