2

我想用 KeychainItemWrapper 将 UUID 保存在钥匙串中,所以我在MyKeychainManager.m中添加了以下方法:

#define keychain_idenentify @"com.myapp.bundle1"

+ (void)saveUUID:(NSString *)UUID{
  if([MyKeychainManager getUUID].length > 0) {
    return;
  }
  KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc]initWithIdentifier:keychain_idenentify accessGroup:nil];
  [keychain setObject:UUID forKey:(__bridge id)kSecAttrLabel];
}

+ (NSString *)getUUID {
  KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc]initWithIdentifier:keychain_idenentify accessGroup:nil];

  NSString *uuidString = [keychain objectForKey:(__bridge id)kSecAttrLabel];
  return uuidString;
}

但是在我将keychain_identify更改为com.otherApp.bundle后,它崩溃了

结果 = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL); NSAssert(result == noErr, @"无法添加钥匙串项。");

错误是错误 - 25299

为什么会这样以及如何解决这个问题?我应该选择哪个,例如kSecAttrLabel?我将它更改为kSecAttrService它很有趣,但我不知道是否还有其他潜在的错误。

任何帮助将不胜感激。

4

2 回答 2

2

我花了很多天来解决同样的问题。终于找到了自己太容易擦肩而过的原因。

这是钥匙串的一个重要常数。看看代码。(假设我第一次在目标中使用钥匙串)

KeychainItemWrapper *test1 = [[KeychainItemWrapper alloc] initWithIdentifier:@"test10"  accessGroup:nil];
[test1 setObject:(id)@"value1" forKey:(id)kSecValueData];
//Normally it works

KeychainItemWrapper *test2 = [[KeychainItemWrapper alloc] initWithIdentifier:@"test20"  accessGroup:nil];
//At this point , we meet the crash with the message of 'Couldn't add the Keychain Item.'
[test2 setObject:(id)@"value2" forKey:(id)kSecValueData];

即使 'initWithIdentifier' 的名称不同,常量 'kSecAttrAccount' 也必须是唯一的。它的默认值为“”(即为空)。一旦使用了钥匙串包装器,就会保存它的“kSecAttrAccount”。因此,当您使用另一个“initWithIdentifier”时,您需要非常注意“kSecAttrAccount”。

我可以通过添加一些代码来修复上述代码的崩溃。

    KeychainItemWrapper *test1 = [[KeychainItemWrapper alloc] initWithIdentifier:@"test10"  accessGroup:nil];
[test1 setObject:@"test1" forKey:(id)kSecAttrAccount];
[test1 setObject:(id)@"value1" forKey:(id)kSecValueData];

KeychainItemWrapper *test2 = [[KeychainItemWrapper alloc] initWithIdentifier:@"test20"  accessGroup:nil];
[test2 setObject:@"test2" forKey:(id)kSecAttrAccount];
[test2 setObject:(id)@"value2" forKey:(id)kSecValueData];

有关更多信息,如果您使用 KeychainItemWrapper 的 accessGroup,如上所述,kSecAttrAccount 必须是唯一的,无论是否使用 accessGroup。

下面是一个例子。

KeychainItemWrapper *test = [[KeychainItemWrapper alloc] initWithIdentifier:@"test"  accessGroup:"App_ID.SampleName"];

如您所知,App_ID 应在 Apple 开发人员处创建,SampleName 应在您的应用程序目标的 KeyChain Sharing 功能中设置。这 '。' 必须在 App_ID 和 SampleName 之间添加。这是一个关键点。

设置方法请参考其他人上传的帖子。

于 2019-05-30T04:26:18.370 回答
1

此错误表示具有此标识符的项目已存在 ( https://osstatus.com/search/results?platform=all&framework=all&search=-25299 )。尝试从钥匙串中删除它,然后您的代码应该可以工作。

于 2019-04-29T08:32:33.490 回答