2010-08-29 15 views
5

Io uso il seguente codice per recuperare le credenziali di accesso da iPhone portachiavi:problema utilizzando KeychainItemWrapper

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"Test" accessGroup:nil]; 
NSString *username = [wrapper objectForKey:(id)kSecAttrAccount]; 
NSString *password = [wrapper objectForKey:(id)kSecValueData]; 
[wrapper release]; 

Sono sotto l'impressione che la prima volta che un utente avvia l'applicazione, né il nome utente né la password potrebbe essere recuperato dal portachiavi, quindi username e password dovrebbe essere uguale a nil. Tuttavia, non è stato possibile stampare nessuna di queste variabili utilizzando NSLog.

Qualche suggerimento?

+0

cosa stavi in ​​grado di stampare? Perché non imposti un breakpoint e ispezioni gli oggetti mentre sei in esecuzione? – vfn

+0

Niente. Nulla si presenta quando ho provato a stampare gli oggetti. Ispezionandoli visualizza solo l'indirizzo sotto forma di 0xSOMETHING. –

+0

@ Una domanda stupida, ma hai verificato che 'wrapper' non è nullo? Inoltre, sono d'accordo con vfn sull'impostazione dei punti di interruzione ... –

risposta

5

La tua ipotesi è sbagliato- sulla creazione, la "kSecAttrAccount" e "kSecValueData" non sono impostati a zero. Sono impostati su una stringa vuota (cioè ""). Quindi, questo codice restituisce true:

[username isEqualToString:@""] // returns true on creation 
+1

Invece di eseguire un confronto diretto tra stringhe, il controllo della lunghezza funziona altrettanto bene. '[lunghezza del nome utente]> 0' – orkoden

8
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"Test" accessGroup:nil]; 
NSString *username = [wrapper objectForKey:(id)kSecAttrAccount]; 
NSString *password = [wrapper objectForKey:(id)kSecValueData]; 

// initially all these are empty 
NSLog(@"username - %@", username); // username - 
NSLog(@"password - %@", password); // password - 

//if empty set your credentials 
if ([username isEqualToString:@""]) { 
    [wrapper setObject:@"your username here" forKey:(id)kSecAttrAccount]; 
} 
if ([password isEqualToString:@""]) { 
    [wrapper setObject:@"your password here" forKey:(id)kSecValueData]; 
} 

//get the latest credentials - now you have the set values 
username = [wrapper objectForKey:(id)kSecAttrAccount]; 
password = [wrapper objectForKey:(id)kSecValueData]; 

NSLog(@"username - %@", username); // username - your username here 
NSLog(@"password - %@", password); // password - your password here 

// reset your keychain items - if needed 
[wrapper resetKeychainItem]; 
[wrapper release]; 
+0

La parte di cui non sono sicuro è "inizialmente tutti questi sono vuoti". Come accennato nella mia domanda, non ho potuto ottenere 'NSLog' per stampare uno di questi valori. Sto cercando di aprire la finestra di dialogo di accesso se sono vuoti/zero, ma non funziona. –

0

Se i valori sono inizialmente pari a zero, utilizzando

if ([username isEqualToString:@""]) 

valuterà FALSE. Si potrebbe utilizzare

if (!username) 

invece

1

stesso errore per me, ho controllato il valore restituito per writeToKeychain funzione nel KeychainItemWrapper.m file. Il valore restituito è uguale a errSecDuplicateItem. Non so perché, ma sembra che la funzione SecItemCopyMatching non funzioni correttamente. (Per il mio altro progetto funziona correttamente).

ho cambiato i codici per ora e lavorare per me: codici aggiornati per writeToKeychain in KeychainItemWrapper.m di file:

- (void)writeToKeychain 
{ 
    NSDictionary *attributes = NULL; 
    NSMutableDictionary *updateItem = NULL; 
    OSStatus result; 



    if (SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes) == noErr) 
    { 
     // First we need the attributes from the Keychain. 
     updateItem = [NSMutableDictionary dictionaryWithDictionary:attributes]; 
     // Second we need to add the appropriate search key/values. 
     [updateItem setObject:[genericPasswordQuery objectForKey:(id)kSecClass] forKey:(id)kSecClass]; 

     // Lastly, we need to set up the updated attribute list being careful to remove the class. 
     NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:keychainItemData]; 
     [tempCheck removeObjectForKey:(id)kSecClass]; 

#if TARGET_IPHONE_SIMULATOR 
     // Remove the access group if running on the iPhone simulator. 
     // 
     // Apps that are built for the simulator aren't signed, so there's no keychain access group 
     // for the simulator to check. This means that all apps can see all keychain items when run 
     // on the simulator. 
     // 
     // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the 
     // simulator will return -25243 (errSecNoAccessForItem). 
     // 
     // The access group attribute will be included in items returned by SecItemCopyMatching, 
     // which is why we need to remove it before updating the item. 
     [tempCheck removeObjectForKey:(id)kSecAttrAccessGroup]; 
#endif 

     // An implicit assumption is that you can only update a single item at a time. 

     result = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck); 
     NSAssert(result == noErr, @"Couldn't update the Keychain Item."); 
    } 
    else 
    { 
     // No previous item found; add the new one. 

     result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL); 
     NSLog(@"%@",keychainItemData); 
     NSLog(@"res : %ld",result); 
     if(result == (OSStatus)errSecDuplicateItem) 
     { 
      NSLog(@"updttttt"); 
      // First we need the attributes from the Keychain. 
      updateItem = [NSMutableDictionary dictionaryWithDictionary:attributes]; 
      // Second we need to add the appropriate search key/values. 
      [updateItem setObject:[genericPasswordQuery objectForKey:(id)kSecClass] forKey:(id)kSecClass]; 

      // Lastly, we need to set up the updated attribute list being careful to remove the class. 
      NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:keychainItemData]; 
      [tempCheck removeObjectForKey:(id)kSecClass]; 

#if TARGET_IPHONE_SIMULATOR 
      // Remove the access group if running on the iPhone simulator. 
      // 
      // Apps that are built for the simulator aren't signed, so there's no keychain access group 
      // for the simulator to check. This means that all apps can see all keychain items when run 
      // on the simulator. 
      // 
      // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the 
      // simulator will return -25243 (errSecNoAccessForItem). 
      // 
      // The access group attribute will be included in items returned by SecItemCopyMatching, 
      // which is why we need to remove it before updating the item. 
      [tempCheck removeObjectForKey:(id)kSecAttrAccessGroup]; 
#endif 

      // An implicit assumption is that you can only update a single item at a time. 

      result = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck); 
      NSAssert(result == noErr, @"Couldn't update the Keychain Item."); 
      return; 
     }//if(result == errSecDuplicateItem)* 
     NSAssert(result == noErr, @"Couldn't add the Keychain Item."); 
    } 
} 
Problemi correlati