使用LAContext和touchIDAuthenticationAllowableReuseDuration获取钥匙串项

man*_*avi 5 security objective-c ios touch-id swift

我正在尝试添加touchIDAuthenticationAllowableReuseDuration我的应用程序的功能.我使用Touch ID将用户验证到应用程序中,同时从钥匙串中恢复项目.在我尝试添加它之前没有问题,它总是要求Touch ID或者如果设备密码不可用.到目前为止,我已经设法使它做同样的事情,并且当在指定的超时内打开应用程序时,它不显示Touch ID提示,因为它应该,如果我所做的只是验证用户我我要完成,但我遇到的问题是我还想从钥匙串中恢复一个项目,当成功绕过提示时,但是一旦我打电话,SecItemCopyMatching(…)我就不会收到该项目,而是我继续errSecAuthFailed.

我到处看都在线,我发现的最好的东西是Apple的示例代码KeychainTouchID,但同样,它不同时进行身份验证和从钥匙串中获取项目,我试图将其添加到他们的代码中我也一直得到同样的错误.

以前有人试过这样的事吗?你是怎么做到的?这是我现在的代码:

SecAccessControlRef sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlTouchIDAny, nil);

NSString *localizedReason = NSLocalizedString(@"Authenticate to access app", nil);

LAContext *context = [[LAContext alloc] init];
context.touchIDAuthenticationAllowableReuseDuration = 5;

[context evaluateAccessControl:sacObject operation:LAAccessControlOperationUseItem localizedReason:localizedReason reply:^(BOOL success, NSError *error) {
    if (success) {
        NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
                                (__bridge id)kSecAttrService: PASSCODE_KEY,
                                (__bridge id)kSecReturnData: @YES,
                                (__bridge id)kSecUseOperationPrompt: localizedReason,
                                (__bridge id)kSecUseAuthenticationUI: (__bridge id)kSecUseAuthenticationUIAllow,
                                (__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacObject,
                                (__bridge id)kSecUseAuthenticationContext: context
                                };

        CFTypeRef dataTypeRef = NULL;

        OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)(query), &dataTypeRef);
        // This works when using Touch ID / passcode, but I get errSecAuthFailed when the prompt isn't shown because of the reuse duration.
        if (status == errSecSuccess) {
            NSData *resultData = (__bridge_transfer NSData *)dataTypeRef;
            NSString *result = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
            self.recoveredString = result;

        } else {
            self.recoveredString = @"";
        }
    } else {
        self.recoveredString = @"";
        CFRelease(sacObject);
    }
}];
Run Code Online (Sandbox Code Playgroud)

小智 1

不要每次都创建 LAContext 对象。只需保留evaluateAccessControl已成功的 LAContext 对象即可。这样就不需要设置了touchIDAuthenticationAllowableReuseDuration。如果您调用已成功的evaluateAccessControlLAContext 对象evaluateAccessControl,则将立即成功调用回复回调,而不会要求用户再次进行身份验证

当您希望用户再次进行身份验证时,只需使 LAContext 对象无效即可。