出于某种原因,我在OSX 10.8.4上调用SecItemCopyMatching时得到一个空字典。相应的项目位于钥匙串中,包含用户名和密码。 SecItemCopyMatching创建它(errSecSuccess)但结果字典只包含0个条目。我希望它至少有用户名和密码数据,所以我的请求有什么问题?
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);
答案 0 :(得分:2)
请求中有错误。我把关键和对象搞混了。
[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);