2013-06-27 56 views
1

由於某些原因,我在調用OSX 10.8.4上的SecItemCopyMatching時收到了空字典。相應的項目位於鑰匙串中幷包含用戶名和密碼。 SecItemCopyMatching創建它(errSecSuccess),但結果字典只包含0個條目。我希望它至少有用戶名和密碼數據,那麼我的請求有什麼問題?SecItemCopyMatching返回空字典

OSStatus status; 
NSMutableDictionary *query = [NSMutableDictionary dictionary]; 
[query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 
[query setObject:(id)kSecReturnAttributes forKey:(id)kCFBooleanTrue]; 
[query setObject:@"MyService" forKey:(id)kSecAttrService]; 

CFDictionaryRef dictRef = NULL; 
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&dictRef); 
if (status != errSecSuccess) { 
    CFStringRef errorRef = SecCopyErrorMessageString(status, NULL); 
    NSLog(@"%s: %@", __FUNCTION__, (__bridge NSString *)errorRef); 
    CFRelease(errorRef); 
    return nil; 
} 

// --> dictRef empty 

if (dictRef != NULL) CFRelease(dictRef); 

enter image description here

+0

我不能,爲什麼你得到一個空的字典回來一看便知,但密碼沒有被返回並不奇怪。 kSecReturnAttributes的頭文件說:_Specifies一個字典鍵,其值爲CFBooleanRef類型。值爲kCFBooleanTrue表示應該返回一個項目(在CFDictionaryRef中)的(未加密的)屬性._ – bdash

+0

你是對的,它沒有要求允許訪問鑰匙串。在請求中有一個愚蠢的錯誤:[查詢setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; – Gamadril

回答

1

有在請求一個錯誤。我混淆了關鍵和對象。

[query setObject:(id)kSecReturnAttributes forKey:(id)kCFBooleanTrue]; 

必須

[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 

然而由於bdash指出的那樣,將返回唯一的非加密特性,如用戶名。要獲得密碼有必要的傳遞

[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 

所以在這裏我現在有另一個請求:

OSStatus status; 
NSMutableDictionary *query = [NSMutableDictionary dictionary]; 
[query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 
[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 
[query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; 
[query setObject:@"MyService" forKey:(id)kSecAttrService]; 

// get username 
CFDictionaryRef dictRef = NULL; 
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&dictRef); 
if (status != errSecSuccess) { 
    CFStringRef errorRef = SecCopyErrorMessageString(status, NULL); 
    NSLog(@"%s: %@", __FUNCTION__, (__bridge NSString *)errorRef); 
    CFRelease(errorRef); 
    return nil; 
} 

NSString *username = (__bridge NSString *)CFDictionaryGetValue(dictRef, kSecAttrAccount); 
CFRelease(dictRef); 

// get password 
[query removeObjectForKey:(id)kSecReturnAttributes]; 
[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 
CFDataRef dataRef = NULL; 
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&dataRef); 
if (status != errSecSuccess) { 
    CFStringRef errorRef = SecCopyErrorMessageString(status, NULL); 
    NSLog(@"%s: %@", __FUNCTION__, (__bridge NSString *)errorRef); 
    CFRelease(errorRef); 
    return nil; 
} 

NSString *password = [[NSString alloc] initWithData:(__bridge NSData *)(dataRef) encoding:NSUTF8StringEncoding]; 
CFRelease(dataRef);