我目前正在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中设置,以防止事情超时。我对钥匙链的工作没有任何问题,但是在我的令牌被填满之前我不会让事情继续下去。
修改 我已经弄清了我的问题,他们的钥匙串没有从后台检索值。我将在下面发布答案并接受它,因为我觉得这个问题可能会在以后对其他人有用。
答案 0 :(得分:101)
我的问题接近原因,但原因并不完全。经过博客后阅读博客,经过教程后的教程,我终于找到了一个可以发现可能发生的事情的文章。
锁定主屏幕。钥匙串教程始终将钥匙串的辅助功能设置留空,因此默认为Apple最低/最安全的访问级别。但是,如果用户在锁定屏幕上有密码,则此级别不允许钥匙串访问。答对了!这解释了零星的行为以及为什么这只发生在一小部分用户身上。
一行代码,解决了整个问题。
[wrapper setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];
在我设置用户名和密码值的位置添加此行。奇迹般有效。希望这会帮助那里的人。直到我能把这些碎片拼凑起来,这让我感到很困惑。
答案 1 :(得分:54)
使用kSecAttrAccessibleAfterFirstUnlock
代替kSecAttrAccessibleAlways
。
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]);
}