iOS TouchID验证和Keychain结合使用

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地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值