2011-11-08 27 views
10

Ho appena trovato un problema interessante con la mia app. Nell'applicazione sto salvando il nome utente e la password dell'utente sul portachiavi.iOS KeychainItemWrapper non si aggiorna

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

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

Quando questo codice viene eseguito in Debug sembra funzionare correttamente. Si aggiorna ogni volta e in seguito posso recuperare gli oggetti dal portachiavi. Quando viene eseguito in distribuzione, tuttavia, il portachiavi non viene mai aggiornato. Ho verificato che sì queste righe di codice vengono colpite in entrambe le build. Sto usando Xcode 4.2 con l'SDK iOS5 e l'applicazione su un iPad 2 con iOS5 installato.

risposta

16

Ho anche avuto questo problema, e mi ci sono voluti per sempre di capire

Esiste una versione di "KeychainWrapper" galleggianti intorno che ha il SecItemUpdate all'interno di un NSAssert (tra le altre cose).

Chiunque abbia fatto questo è un deficiente !, quando costruisce per la distribuzione/distribuzione ogni NSAssert viene annullato, il che significa che il codice non viene nemmeno eseguito.

Ad esempio:

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

deve diventare

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

Notate come il SecItemUpdate attuale viene spostato al di fuori del NSAssert, e invece il risultato è controllato

Nota importante: Tentare aggiornare un valore per kSecValueData, senza specificare anche un valore per kSecAttrAccount, farà sì che anche l'asserzione fallisca. Quindi, se il vostro intento è quello di memorizzare una singola stringa di dati sensibili (come ad esempio un elenco di numeri di carta di credito), assicurarsi di memorizzare un testo "nome di account" nell'attributo kSecAttrAccount, in questo modo:

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)]; 
} 
+0

L'avevo capito e questo era essenzialmente il problema. Grazie. – iHorse

+0

Questo sembra essere risolto nella v1.2 di KeychainWrapper, disponibile dal codice di esempio Xcode – Olaf

14

quando si include

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

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

si doveva anche includere

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

O ottengo un errore "SIGABRT". (Myappstring) è una stringa che definisce la tua applicazione.

Forse mi manca qualcosa, questo dovrebbe essere fatto almeno una volta.

+0

KeychainItemWrapper funzionava principalmente per me, funzionava su molti indirizzi e-mail (memorizzati come nome utente in kSecAttrAccount), ma una e-mail in particolare non funzionava. Ho quindi aggiunto la riga sopra per kSecAttrService e ora tutto è perfetto! -Grazie @Andres – dbDev

+0

ho lottato con esso per un bel po '. Sono contento che abbia aiutato –

+1

Questa correzione ha funzionato per me. È difficile capire cosa sta succedendo dai messaggi di errore, perché se hai mai impostato in precedenza questi valori correttamente, non vedrai un errore. Solo quando si modifica initWithIdentifier: valore AND non riesce a impostare kSecAttrService, quindi si inizia a ricevere errori. – carbocation