iOS KeychainItemWrapper не обновляется - PullRequest
11 голосов
/ 08 ноября 2011

Я только что обнаружил интересную проблему с моим приложением. В приложении я сохраняю имя пользователя и пароль пользователя в цепочке для ключей.

keychainWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyLoginPassword" accessGroup:nil];

[keychainWrapper setObject:usernameField.text forKey:(id)kSecAttrAccount];
[keychainWrapper setObject:passwordField.text forKey:(id)kSecValueData];

Когда этот код запускается в Debug, он, кажется, работает просто отлично. Он обновляется каждый раз, и позже я могу получить элементы из цепочки для ключей. Однако когда он запускается в Distribution, цепочка для ключей никогда не обновляется. Я подтвердил, что да, эти строки кода встречаются в обеих сборках. Я использую Xcode 4.2 с iOS5 SDK и запускаю приложение на iPad 2 с установленной iOS5.

Ответы [ 2 ]

17 голосов
/ 23 ноября 2011

У меня тоже была эта проблема, и мне потребовалось целую вечность, чтобы выяснить

Существует версия "KeychainWrapper", которая имеет свой SecItemUpdate в NSAssert (среди прочего).

Кто бы это ни сделал, это придурок !, при сборке для выпуска / распространения каждый NSAssert обнуляется, что означает, что код даже не запускается.

Например:

NSAssert(SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck), @"Couldn't update the Keychain Item." );

Требуетсястать

OSStatus status = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck);
NSAssert(status == noErr, @"Couldn't update the Keychain Item." );

Обратите внимание, как фактическое SecItemUpdate перемещается за пределы NSAssert, и вместо этого проверяется результат

Важное примечание: Попытка обновить значение для kSecValueData, также не указывая значениедля kSecAttrAccount также приведет к сбою подтверждения.Итак, если вы хотите сохранить одну строку конфиденциальных данных (например, список номеров кредитных карт), обязательно сохраните некоторый текст «имени учетной записи» в атрибуте kSecAttrAccount, например:

static NSString* kCardListXML = @"cardListXML";
static NSString* cardListAccountName = @"cardListAccount";

-(void)setCardListXML:(NSString*)xml {
  KeychainItemWrapper* wrapper =
    [[KeychainItemWrapper alloc] initWithIdentifier:kCardListXML accessGroup:nil];
  [wrapper setObject:cardListAccountName forKey:(id)CFBridgingRelease(kSecAttrAccount)];
  [wrapper setObject:xml forKey:(id)CFBridgingRelease(kSecValueData)];
}    

-(NSString*)getCardListXML {
  KeychainItemWrapper* wrapper =
    [[KeychainItemWrapper alloc] initWithIdentifier:kCardListXML accessGroup:nil];
  [wrapper setObject:cardListAccountName forKey:(id)CFBridgingRelease(kSecAttrAccount)];
  return [wrapper objectForKey:CFBridgingRelease(kSecValueData)];
}
16 голосов
/ 07 декабря 2011

Когда вы включаете

keychainWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyLoginPassword" accessGroup:nil];

[keychainWrapper setObject:usernameField.text forKey:(id)kSecAttrAccount];
[keychainWrapper setObject:passwordField.text forKey:(id)kSecValueData];

, вы также должны были включить

[keychainWrapper setObject:@"Myappstring" forKey: (id)kSecAttrService];

Или я получаю ошибку "SIGABRT".(Myappstring) - это строка, определяющая ваше приложение.

Может быть, я что-то упустил, это следует сделать хотя бы один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...