2013-06-27 54 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);