2010-08-29 9 views
5

utilizo el siguiente código para recuperar las credenciales de acceso de la llave iPhone:problema usando KeychainItemWrapper

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

estoy bajo la impresión de que la primera vez que un usuario inicia la aplicación, ni nombre de usuario ni contraseña podría ser recuperado del llavero, por lo que username y password debe ser igual a nil. Yo, sin embargo, no pude imprimir ninguna de estas variables usando NSLog.

¿Alguna sugerencia?

+0

¿Qué estaba capaz de imprimir? ¿Por qué no establece un punto de interrupción e inspecciona los objetos mientras se ejecuta? – vfn

+0

Nada. Nada aparece cuando traté de imprimir los objetos. Al inspeccionarlos solo se muestra la dirección en la forma de 0xSOMETHING. –

+0

@Anh pregunta estúpida, pero ¿has verificado que 'wrapper' no es nulo? Además, estoy de acuerdo con vfn sobre el establecimiento de puntos de interrupción ... –

Respuesta

5

Su hipótesis es mal- en la creación, el "kSecAttrAccount" y "kSecValueData" no se ajusta a cero. Están configurados en una cadena vacía (es decir, ""). Por lo tanto, este código devolverá true:

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

En lugar de hacer una comparación directa de cadenas, la verificación de la longitud funciona igual de bien. '[longitud del nombre de usuario]> 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 de la que no estoy seguro es "al principio todos estos están vacíos". Como mencioné en mi pregunta, no pude hacer que 'NSLog' imprimiera ninguno de estos valores. Estoy intentando mostrar el cuadro de diálogo de inicio de sesión si están vacíos/nulos, pero no funciona. –

0

Si los valores son inicialmente cero, utilizando

if ([username isEqualToString:@""]) 

evaluará como FALSE. Se podría utilizar

if (!username) 

lugar

1

mismo error para mí, he comprobado el valor de retorno para writeToKeychain función en KeychainItemWrapper.m archivo. El valor de retorno es igual a errSecDuplicateItem. No sé por qué pero parece que la función SecItemCopyMatching no funciona correctamente. (Para que mi otro proyecto funcione correctamente).

me cambiaron los códigos para el presente y trabajando para mí: códigos actualizados para writeToKeychain en KeychainItemWrapper.m archivo:

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