【问题标题】:SecItemCopyMatching is returning nilSecItemCopyMatching 返回 nil
【发布时间】:2020-07-15 22:05:35
【问题描述】:

我有这个方法

- (NSString *)bundleSeedID:(NSError **)error __attribute__((annotate("oclint:suppress"))) {
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
                       (__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass,
                       BUNDLE_SEED_ID, kSecAttrAccount,
                       EMPTY_STRING, kSecAttrService,
                       (__bridge NSString *)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, (__bridge NSString *)kSecAttrAccessible,
                       (id)kCFBooleanTrue, kSecReturnAttributes,
                       nil];
CFDictionaryRef result = nil;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if (status == errSecItemNotFound) {
    status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
}

if (status != errSecSuccess) {
    if (error) *error = [ErrorUtils bundleSeedErrorWithCode:(int)status];
    return nil;
}
NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup];
NSArray *components = [accessGroup componentsSeparatedByString:@"."];
NSString *bundleSeedID = [[components objectEnumerator] nextObject];
CFRelease(result);
return bundleSeedID;
}

我不明白为什么有时 result 为空。

注意:此代码始终在主线程中执行,无需任何异步调用

你能帮我理解为什么会这样吗?此代码仅在我打开应用程序时执行。

我知道我可以检查 result 是否为空,然后我不会 CFRelease(result); 但预计不会发生这种情况。应用程序崩溃后,如果我再次打开它,一切正常。

提前谢谢????

【问题讨论】:

    标签: ios objective-c keychain


    【解决方案1】:

    您很可能在设备锁定时在后台启动。当设备被锁定时,您无法访问钥匙串中的某些受保护数据;您应该会在错误消息中看到这一点。

    您似乎确实将kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly 传递给了创建,可能是您在创建钥匙串项后将kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly 添加到您的应用程序中(或者您在其他地方创建时没有传递它)。

    您的代码检查errSecItemNotFound,但如果我没记错的话,您应该检查errSecDataNotAvailable 以检测此问题。 (您也可以检查 UIApplication 的 `isProtectedDataAvailable。)当然,在这种情况下您不应该尝试创建项目;你只需要一种优雅的方式来失败。

    在第一次解锁之前启动是相当罕见的,但这也是可能的,并且钥匙串将不可用。例如,我记得挂起的蓝牙连接可能会导致这种情况。我不相信推送通知可以在那种状态下启动应用程序,但这是可能的。

    无论如何,您都需要检查意外错误并处理nil 值。

    【讨论】:

    • 感谢您的回答罗。但即使我删除 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,我仍然得到结果 == null。有什么理由吗?
    • 那不会更好;这会使我所描述的情况变得更糟。 kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly 仅在您创建项目时相关。它设置保护级别。
    • “ThisDeviceOnly”也很重要。如果用户将他们的钥匙串同步到另一台设备(特别是如果他们购买了新手机),则不会复制该项目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-17
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多