iOS KeychainItemWrapper не обновляется
Я только что нашел интересную проблему с моим приложением. В приложении я сохраняю имя пользователя и пароль пользователя в цепочке для ключей.
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 ответа
У меня тоже была эта проблема, и мне понадобилось вечно, чтобы выяснить,
Существует версия "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)];
}
Когда вы включаете
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) - это строка, определяющая ваше приложение.
Может быть, я что-то упустил, это нужно сделать хотя бы один раз.