2010-08-29 6 views
5

J'utilise le code suivant pour récupérer les informations de connexion du trousseau iPhone:Problème d'utilisation KeychainItemWrapper

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

Je suis sous l'impression que la première fois qu'un utilisateur lance l'application, ni nom d'utilisateur ni mot de passe pourrait être récupéré à partir du trousseau, donc username et password doit être égal à nil. Cependant, je n'ai pas pu imprimer l'une de ces variables en utilisant NSLog.

Des suggestions?

+0

Qu'est-ce que vous avez pu imprimer? Pourquoi ne pas définir un point d'arrêt et inspecter les objets en cours d'exécution? – vfn

+0

Rien. Rien ne se montre quand j'ai essayé d'imprimer les objets. Les inspecter n'affiche que l'adresse sous la forme 0xSOMETHING. –

+0

@Anh question stupide, mais avez-vous vérifié que «wrapper» n'est pas nul? Aussi, je suis d'accord avec vfn sur la mise en place de points de rupture ... –

Répondre

5

Votre hypothèse est wrong- sur la création, la « kSecAttrAccount » et « kSecValueData » ne sont pas mis à zéro. Ils sont définis sur une chaîne vide (c'est-à-dire ""). Donc, ce code retourne vrai:

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

Au lieu de faire une comparaison directe, la vérification de la longueur fonctionne aussi bien. '[longueur du nom d'utilisateur]> 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 partie dont je ne suis pas sûr est "tout d'abord tous ceux-ci sont vides". Comme mentionné dans ma question, je n'ai pas pu obtenir NSLog pour imprimer ces valeurs. J'essaye d'ouvrir la boîte de dialogue de connexion si elles sont vides/nulles, mais cela ne fonctionne pas. –

0

Si les valeurs sont initialement nulle, en utilisant

if ([username isEqualToString:@""]) 

évaluera FALSE. Vous pouvez utiliser

if (!username) 

au lieu

1

erreur même pour moi, j'ai vérifié la valeur de retour pour writeToKeychain fonction dans le fichier KeychainItemWrapper.m. La valeur de retour est égale à errSecDuplicateItem. Je ne sais pas pourquoi mais il semble que la fonction ne fonctionne pas correctement. (Pour que mon autre projet fonctionne correctement).

j'ai changé les codes pour l'instant et le travail pour moi: codes mis à jour pour writeToKeychain dans le fichier KeychainItemWrapper.m:

- (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."); 
    } 
}