iOS KeyChain不从后台检索值

时间:2012-05-10 15:03:52

标签: iphone ios background keychain lockscreen

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

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 个答案:

答案 0 :(得分:101)

我的问题接近原因,但原因并不完全。经过博客后阅读博客,经过教程后的教程,我终于找到了一个可以发现可能发生的事情的文章。

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

一行代码,解决了整个问题。

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

在我设置用户名和密码值的位置添加此行。奇迹般有效。希望这会帮助那里的人。直到我能把这些碎片拼凑起来,这让我感到很困惑。

答案 1 :(得分:54)

使用kSecAttrAccessibleAfterFirstUnlock代替kSecAttrAccessibleAlways


来自Apple's documentation

  

kSecAttrAccessibleAfterFirstUnlock
  钥匙串项目中的数据不能   重启后访问,直到设备解锁一次   由用户。

     

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

答案 2 :(得分:1)

就我而言,watchOS2访问iOS端的钥匙串数据。

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

有些情况会变成: :SecOSStatusWith错误:[ - 25308]错误域= NSOSStatusErrorDomain代码= -25308“ks_crypt:e00002e2未能'oe'项目(类6,包:0)访问锁定钥匙串时尝试的项目。” UserInfo = {NSDescription = ks_crypt:e00002e2未能'oe'项目(类6,包:0)访问锁定钥匙串时尝试的项目。}

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

答案 3 :(得分: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]);
}