2010-08-29 5 views
5

Я использую следующий код, чтобы получить учетные данные из брелка iPhone:Проблема с использованием KeychainItemWrapper

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

Я нахожусь под впечатлением, что первый раз, когда пользователь запускает приложение, ни имя пользователя, ни пароль может быть извлеченные из брелка, поэтому username и password должны быть равны nil. Я, однако, не смог распечатать любую из этих переменных, используя NSLog.

Любые предложения?

+0

Что вы смогли напечатать? Почему вы не устанавливаете точку останова и не проверяете объекты во время работы? – vfn

+0

Ничего. При попытке распечатать объекты ничего не появляется. Проверка их только отображает адрес в виде 0xSOMETHING. –

+0

@ О, глупый вопрос, но вы подтвердили, что 'wrapper' не ноль? Кроме того, я согласен с vfn о настройке точек останова ... –

ответ

5

Ваше предположение wrong- по созданию, «kSecAttrAccount» и «kSecValueData» НЕ установлен в ноль. Они установлены в пустую строку (то есть, ""). Таким образом, этот код возвращает истину:

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

Вместо прямого сравнения строк, проверка длины работает так же хорошо. '[длина имени пользователя]> 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

Часть, о которой я не уверен, «изначально все эти пустые». Как уже упоминалось в моем вопросе, я не мог заставить 'NSLog' печатать любые из этих значений. Я пытаюсь открыть диалог входа в систему, если они пусты/ноль, но это не работает. –

0

Если значения изначально ноль, используя

if ([username isEqualToString:@""]) 

оценит ЛОЖЬ. Вы можете использовать

if (!username) 

вместо

1

же ошибка для меня, я проверил возвращаемое значение для writeToKeychain функции в KeychainItemWrapper.m файле. Возвращаемое значение равно errSecDuplicateItem. Я не знаю, почему, но похоже, что функция SecItemCopyMatching работает неправильно. (Для моего другого проекта, работающего правильно).

Я изменил коды сейчас и работаем для меня: Обновленных кодов для writeToKeychain в 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."); 
    } 
} 
Смежные вопросы