我使用Apple wraper for the keychain,并尝试在其上保存一个项目(在模拟器,ios 4.1中运行)。
我之前没有使用钥匙链。
我收到此错误:
无法添加钥匙串项目。错误 - 25299
在KeychainItemWrapper.m第304行:
// No previous item found; add the new one.
result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);
NSAssert( result == noErr, @"Couldn't add the Keychain Item." );
这是我保存的方式:
- (void) saveKey:(NSString *)key value:(NSString *)value {
KeychainItemWrapper *keyItem = [[KeychainItemWrapper alloc] initWithIdentifier:key accessGroup:nil];
[keyItem setObject:value forKey:(id)kSecValueData];
[keyItem release];
}
这是api试图保存的值:
<CFBasicHash 0x7231f60 [0x320d380]>{type = mutable dict, count = 5,
entries =>
2 : <CFString 0x2e6eb98 [0x320d380]>{contents = "labl"} = <CFString 0x2fb018 [0x320d380]>{contents = ""}
3 : <CFString 0x2e6efb8 [0x320d380]>{contents = "v_Data"} = <CFString 0x727de60 [0x320d380]>{contents = "dit8"}
4 : <CFString 0x2e6ebc8 [0x320d380]>{contents = "acct"} = <CFString 0x2fb018 [0x320d380]>{contents = ""}
5 : <CFString 0x2e6eb58 [0x320d380]>{contents = "desc"} = <CFString 0x2fb018 [0x320d380]>{contents = ""}
6 : <CFString 0x2e6ebe8 [0x320d380]>{contents = "gena"} = <CFString 0x2ffd08 [0x320d380]>{contents = "userCode"}
}
答案 0 :(得分:60)
我知道这是几个月前发生的,但我遇到了同样的问题而且很痛苦,所以我想我会分享。我通过添加这一行来解决它:
[self.keychainItemWrapper setObject:@"MY_APP_CREDENTIALS" forKey:(id)kSecAttrService];
//@"MY_APP_CREDENTIALS" can be any string.
我发现此博客条目非常有用: “在数据库术语中,你可以认为它们是两个属性kSecAttrAccount的唯一索引,kSecAttrService要求这两个属性的组合对于钥匙串中的每个条目都是唯一的。” (来自http://useyourloaf.com/blog/2010/4/28/keychain-duplicate-item-when-adding-password.html)。
此外,在使用此代码的Apple示例项目中,他们在app delegate中实例化KeychainItemWrapper。我不知道是否有必要,但我希望尽可能密切关注他们的例子:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//there will be some standard code here.
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MY_APP_CREDENTIALS" accessGroup:nil];
self.keychainWrapper = wrapper;
[self.keychainWrapper setObject:@"MYOBJECT" forKey:(id)kSecAttrService];
[wrapper release];
}
我认为这是包装器代码中的一个错误。逻辑基本上说“这个条目是否已经存在?不,它没有。好的,我会添加它。哎呀,你不能添加它,因为它已经存在了。”
您可能还需要设置kSecAttrAccount;我没有尝试过它而没有设置这个值,因为它打算保存密码配置的用户名:
[self.wrapper setObject:txtUserName.text forKey:(id)kSecAttrAccount];
答案 1 :(得分:9)
根据the documentation,你得到的错误-25299是“errSecDuplicateItem”,意味着你要添加的项目已经存在。查看KeychainItemWrapper的链接代码,我猜测SecItemCopyMatching
调用失败,错误除了errSecItemNotFound(-25300)。
答案 2 :(得分:6)
您可以使用Buzz Andersen的SFHFKeychainUtils轻松存储和获取钥匙串的值。
这是关于如何使用此库的一个小例子。
// To store data
NSError *error = nil;
[SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:kStoredData updateExisting:YES error:&error];
// To retrieve data
NSString *password = [SFHFKeychainUtils getPasswordForUsername:username andServiceName:kStoredData error:&error];
// To delete data from keychain
[SFHFKeychainUtils deleteItemForUsername:username andServiceName:kStoredData error:&error];
答案 3 :(得分:3)
钥匙扣是一种彻底的痛苦。您应该使用Buzz Andersen's STUtils库作为包装器。它会让你的生活变得更加轻松。我从来没有遇到过这个问题。
答案 4 :(得分:1)
对我来说,解决方案是我创建了一个KeychainItemWrapper
“单身”并在整个应用程序中使用它。 (实际上,在我的情况下,我有一个单独的字典,里面装满KeychainItemWrapper
- s,因为我使用的不止一个。)
这解决了我进入一个有效说“这个项目存在于钥匙串上的代码路径的问题吗?没有?然后添加它。哎呀!NSAssert()
我正在尝试添加一个项目已存在(错误-25299)“
虽然我不确定,但我怀疑这个问题与钥匙串同步有关。我和NSUserDefaults
有类似的问题,当我写入NSUD然后,在代码的其他地方,获取standardUserDefaults
并从中读取,并且更新尚未发生(因为我没有'完成[ud synchronize]
,但是。)
在代码中,我的例程看起来像这样:
+ (KeychainItemWrapper*) keyChainWrapperForKeyID: (NSString*) keyID
{
static dispatch_once_t onceToken = 0;
static NSMutableDictionary *rfcuKeyChains = nil;
dispatch_once(&onceToken, ^{
rfcuKeyChains = [NSMutableDictionary new];
});
KeychainItemWrapper *keychain = nil;
@synchronized (rfcuKeyChains)
{
keychain = [rfcuKeyChains objectForKey: keyID];
if (keychain == nil)
{
keychain = [[KeychainItemWrapper alloc] initWithIdentifier: keyID accessGroup: nil];
[rfcuKeyChains setObject: keychain forKey: keyID];
}
}
return keychain;
}
我这样使用它:
KeychainItemWrapper *keychain = [RFCUtils keyChainWrapperForKeyID: keyID];
NSString *firstLaunch = [keychain objectForKey: (__bridge id)(kSecAttrAccount)];
if (firstLaunch == nil)
{
[keychain setObject: MY_APP_KEY forKey: (__bridge id)(kSecAttrAccount)];
}
(等等,其他地方的类似电话。)
答案 5 :(得分:0)
我也遇到了这个问题,并且由于接受者的答案以及使用你们的额外链接而解决了这个问题。
我遇到的问题很有趣,我只需保存一个值,并决定将其存储在 kSecValueData 字段中。那是因为我在转向KeychainItemWrapper之前看到了有关使用钥匙串的其他帖子并开始了我自己的实现。 这导致了以下问题:在我测试的第一台设备(iPad 1st gen)上,我在writeToKeychain中收到错误。我改变了设备(也是ipad 1st gen)并且它工作了!回到第一台设备,它仍然无法正常工作。
所以我知道我之前在设备的钥匙串中做错了什么并且无法轻易恢复。我得到的错误代码是:-T300,在writeToKeychain的SecItemCopyMatching(未找到项目)和-25299之后的SecItemAdd上。 (项目重复)
有了这个问题,这一切都有意义:设备有一个匹配任何新密钥的密钥,但KeychainItemWrapper无法删除它,但无法检索密钥。 一旦我将相同的值添加到字段kSecAttrAccount,它就开始工作了。
长话短说,对于遇到此问题的其他用户,您的问题可能会有所不同,但要注意细节。如果您有-25300(未找到项目),然后是-25299(项目重复);确保您设置的字段定义了钥匙串项的唯一性。如果它不能在一台设备上运行,请尝试使用另一台设备,如果可以,您可以将问题隔离到一台设备上。 Apple keychain错误代码:http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898-CH5g-CJBEABHG(搜索结果代码)
答案 6 :(得分:0)
我尝试了所有解决方案,但我没有任何帮助。它只适用于实际设备,但不适用于模拟器。
我在模拟器上运行它的解决方案是打开&#34;共享钥匙串权利&#34;。