91

我目前正在 iOS KeyChain 中存储用户名(电子邮件)和电子邮件和密码的加盐哈希。我正在使用此处找到的 ARC'ified 版本。

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
[wrapper setObject:APP_NAME forKey:(__bridge id)kSecAttrService];
[wrapper setObject:email forKey:(__bridge id)kSecAttrAccount];
[wrapper setObject:token forKey:(__bridge id)kSecValueData];

当我需要在应用程序处于活动状态时为我的网络调用提取令牌时,这一切都很好。它适用于从干净的启动登录,以及整个网络调用。当应用程序在后台时,麻烦就开始了。

请记住,这只是偶尔发生,我还没有将其固定到特定的 iOS 版本或设备上。

用户旅行一个位置(区域监控),我想用他们的状态更新服务器。我尝试将令牌从钥匙串中拉出,就像我对其他所有网络调用所做的那样,并更新状态。但对于一些用户来说,价值为零。没有它,我无法更新网络内容。为什么这对大多数人有效,但对一小部分人无效?

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
NSString *token = [wrapper objectForKey:(__bridge id)kSecValueData];

我已经回到 keychainwrapper 的非 ARC 版本,但我仍然得到相同的结果。我将不胜感激对此的任何反馈。这只是我用户的一小部分,但这是我想解决而不是担心的问题。提前致谢。

此外,我所有的后台工作都是在 backgroundTask 中设置的,以防止事情超时。我对钥匙串周围的工作没有任何问题,但在我的令牌被填满之前我不会让事情继续进行。

编辑 我已经发现我的问题是他们的钥匙串没有从后台检索值。我将在下面发布答案并接受它,因为我觉得这个问题以后可能对其他人有价值。

4

4 回答 4

114

由于原因,我的问题接近标记,但不完全是。在阅读了一个又一个博客,一个又一个教程之后,我终于找到了一个暗示可能会发生什么的文章。

锁定的主屏幕。钥匙串教程总是将钥匙串的可访问性设置留空,因此它默认为 Apple 的最低/最安全的访问级别。但是,如果用户在锁定屏幕上有密码,则此级别不允许访问钥匙串。答对了!这解释了零星的行为以及为什么这只发生在一小部分用户身上。

一行代码,解决了整个混乱。

[wrapper setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];

在我设置用户名和密码值的地方添加这一行。奇迹般有效。希望这会帮助那里的人。它让我困惑了很长一段时间,直到我能够将这些碎片拼凑在一起。

于 2012-05-14T12:10:31.083 回答
70

使用kSecAttrAccessibleAfterFirstUnlock而不是kSecAttrAccessibleAlways.


来自苹果的文档

kSecAttrAccessibleAfterFirstUnlock
重新启动后无法访问钥匙串项中的数据,直到用户解锁设备一次。

第一次解锁后,数据仍然可以访问,直到下一次重新启动。对于需要由后台应用程序访问的项目,建议使用此选项。使用加密备份时,具有此属性的项目会迁移到新设备。

于 2014-07-08T22:43:35.797 回答
1

在我的例子中,watchOS2 在 iOS 端访问钥匙串数据。

一开始,使用 kSecAttrAccessibleWhenUnlockedThisDeviceOnly。无论 iPhone 是否被锁定,我都可以读取数据。当手表尝试访问钥匙串时我会收到错误,这让我非常困惑::SecTrustEvaluate [leaf IssuerCommonName SubjectCommonName]

在某些情况下,它会变成: : SecOSStatusWith error:[-25308] Error Domain=NSOSStatusErrorDomain Code=-25308 "ks_crypt: e00002e2 failed to 'oe' item (class 6, bag: 0) 在钥匙串被锁定时尝试访问项目。 " UserInfo={NSDescription=ks_crypt: e00002e2 未能“oe”项目(类 6,包:0)在钥匙串锁定时尝试访问项目。}

如果我得到更多信息,我会更新我的答案。

于 2016-02-01T08:46:31.663 回答
0

这可能是由于 Apple 的数据保护政策,从开发人员的角度来看,该政策在某种程度上是模糊的。解决方法是在应用程序启动时检查钥匙串是否可访问,如果不可访问,您可能会根据您的应用程序类型杀死您的应用程序(使用适当的弹出窗口)。

+(BOOL) isKeychainAccessible
{
    NSString *keychainTestKey = @"keychainTestKey";
    NSString *keychainTestValue = @"keychainTestValue";
    [self createKeychainValue:keychainTestValue forIdentifier:keychainTestKey];
    NSString *loadedValue = [self keychainStringFromMatchingIdentifier:keychainTestKey];
    [self deleteItemFromKeychainWithIdentifier:keychainTestKey];
    return ([keychainTestValue isEqualToString: loadedValue]);
}
于 2020-10-28T13:33:13.250 回答