iOS KeyChain 不从后台检索值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10536859/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS KeyChain not retrieving values from background
提问by Bill Burgess
I am currently storing the username (email) and a salted hash of the email and password in the iOS KeyChain. I'm using the ARC'ified version found here.
我目前正在 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];
This all works fine when I need to pull the token out for my network calls while the app is active. It works for logging in from a clean startup, as well as all the network calls throughout. The trouble starts when the app is in the background.
当我需要在应用程序处于活动状态时为我的网络调用提取令牌时,这一切正常。它适用于从干净启动登录,以及整个网络调用。当应用程序在后台时,麻烦就开始了。
Keep in mind, this only happens sporadically and I have yet to pin it down to a specific iOS version or device.
请记住,这只是偶尔发生,我尚未将其确定为特定的 iOS 版本或设备。
The user trips a location (region monitoring) and I want to update the server with their status. I try to pull the token out of the keychain, the same way I do for every other network call, and update the status. But for some users, the value is nil. Without it, I can't update the network stuff. Why would this work for most, but not for a small percentage?
用户旅行了一个位置(区域监控),我想用他们的状态更新服务器。我尝试从钥匙串中取出令牌,就像我对每个其他网络调用所做的一样,并更新状态。但对于一些用户来说,价值为零。没有它,我无法更新网络内容。为什么这对大多数人有效,但对一小部分人无效?
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
NSString *token = [wrapper objectForKey:(__bridge id)kSecValueData];
I've gone back to the non-ARC version of the keychainwrapper, but I still get the same results. I would appreciate any feedback on this. It is only a small part of my users, but it is an issue I would like to fix and not worry about. Thanks in advance.
我已经回到了钥匙串包装器的非 ARC 版本,但我仍然得到相同的结果。我将不胜感激对此的任何反馈。这只是我用户的一小部分,但这是一个我想解决而不用担心的问题。提前致谢。
Also, all of my background work is set up in a backgroundTask to prevent things from timing out. I'm not having any issues with the work surrounding the keychain, but I don't let things go forward until my token is filled.
此外,我所有的后台工作都设置在 backgroundTask 中,以防止事情超时。我对钥匙串周围的工作没有任何问题,但在我的令牌被填满之前,我不会让事情继续进行。
EDITI've figured out my issue with they keychain not retrieving values from the background. I will post the answer below and accept it as I feel this question may become valuable to others later.
编辑我已经解决了我的问题,他们的钥匙串没有从后台检索值。我将在下面发布答案并接受它,因为我觉得这个问题以后可能对其他人有价值。
回答by Bill Burgess
My question was close to the mark for the reason why, but not quite. After reading through blog after blog, tutorial after tutorial, I finally found one that gave off a hint of what might be happening.
由于原因,我的问题接近标记,但不完全。在读完一篇又一篇的博客,一个又一个的教程后,我终于找到了一个暗示可能发生的事情的提示。
Locked home screens. The keychain tutorials always left the accessibility settings for the keychain blank, so it would default to Apple's lowest/safest access level. This level however doesn't allow keychain access if the user has a passcode on the lock screen. Bingo! This explains the sporadic behavior and why this only happens to a small percentage of users.
锁定的主屏幕。钥匙串教程总是将钥匙串的可访问性设置留空,因此它会默认为 Apple 的最低/最安全访问级别。但是,如果用户在锁定屏幕上有密码,则此级别不允许访问钥匙串。答对了!这解释了零星行为以及为什么这种情况只发生在一小部分用户身上。
One line of code, solves the entire mess.
一行代码,解决整个烂摊子。
[wrapper setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];
Add this line where I'm setting the username and password values. Works like a charm. Hope this will help someone out there. It confounded me for quite a while until I was able to put the pieces together.
在我设置用户名和密码值的地方添加这一行。奇迹般有效。希望这会帮助那里的人。它让我困惑了很长一段时间,直到我能够将这些碎片拼凑在一起。
回答by woof
Use kSecAttrAccessibleAfterFirstUnlock
instead of kSecAttrAccessibleAlways
.
使用kSecAttrAccessibleAfterFirstUnlock
代替kSecAttrAccessibleAlways
。
From Apple's documentation:
来自苹果的文档:
kSecAttrAccessibleAfterFirstUnlock
The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications.Items with this attribute migrate to a new device when using encrypted backups.
kSecAttrAccessibleAfterFirstUnlock
直到用户解锁设备一次,才能在重启后访问钥匙串项中的数据。第一次解锁后,数据将保持可访问状态,直到下一次重新启动。建议用于需要由后台应用程序访问的项目。使用加密备份时,具有此属性的项目会迁移到新设备。
回答by skingtree
In my case, watchOS2 accesses keychain data on the iOS side.
就我而言,watchOS2访问在iOS端的钥匙串数据。
At the beginning, kSecAttrAccessibleWhenUnlockedThisDeviceOnly is used. I can read the data no matter iPhone is locked or not. It is very confusing to me that I will receive Error when watch is trying to access the keychain: : SecTrustEvaluate [leaf IssuerCommonName SubjectCommonName]
一开始使用 kSecAttrAccessibleWhenUnlockedThisDeviceOnly。无论 iPhone 是否锁定,我都可以读取数据。这是非常混乱,我认为我会收到错误时手表试图访问钥匙串:SecTrustEvaluate [叶IssuerCommonName SubjectCommonName]
And some case it will become: : SecOSStatusWith error:[-25308] Error Domain=NSOSStatusErrorDomain Code=-25308 "ks_crypt: e00002e2 failed to 'oe' item (class 6, bag: 0) Access to item attempted while keychain is locked." UserInfo={NSDescription=ks_crypt: e00002e2 failed to 'oe' item (class 6, bag: 0) Access to item attempted while keychain is locked.}
在某些情况下它会变成: : 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)在钥匙串被锁定时尝试访问物品。}
I will update my answer if I get more infos.
如果我得到更多信息,我会更新我的答案。