1

我正在使用以下代码:

+ (void)createKeychainItem:(NSString *)name
{
    // Don't create if one already exists
    if ([self getKeychainItem:name] != nil) return;

    NSData *encodedName = [name dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *attributes = @{

                                 (id)kSecAttrAccount : encodedName,
                                 (id)kSecAttrGeneric : encodedName,
                                 (id)kSecAttrLabel   : name,
                                 (id)kSecAttrService : name,
                                 (id)kSecClass       : (id)kSecClassGenericPassword,
                                 };
    OSStatus result = SecItemAdd((CFDictionaryRef)attributes, NULL);
}

+ (NSDictionary *)getKeychainItem:(NSString *)name
{
    // Build the query
    NSData *encodedName = [name dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *query = @{
                            (id)kSecAttrAccount : encodedName,
                            (id)kSecAttrGeneric : encodedName,
                            (id)kSecAttrService : name,
                            (id)kSecClass : (id)kSecClassGenericPassword,
                            (id)kSecMatchLimit : (id)kSecMatchLimitOne,
                            (id)kSecReturnAttributes : (id)kCFBooleanTrue,
                            };
    NSDictionary *output = nil;

    OSStatus result = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&output);

    // Convert the password if it exists
    NSData *passwordData = [output objectForKey:kSecValueData];
    if (passwordData != nil) {
        NSMutableDictionary *mutableOutput = [[output mutableCopy] autorelease];
        NSString *password = [[[NSString alloc] initWithBytes:passwordData length:passwordData.length encoding:NSUTF8StringEncoding] autorelease];
        [mutableOutput setObject:password forKey:(id)kSecValueData];
        output = [[mutableOutput copy] autorelease];
    }

    return output;
}

+ (void)updateKeychainItem:(NSString *)name value:(NSString *)value attribute:(id)attribute
{
    // Get the item
    NSDictionary *values = [self getKeychainItem:name];

    // If we got nothing back, build it
    if (values == nil) {
        [self createKeychainItem:name];
    }

    // Create a query to update
    NSData *encodedName = [name dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *query = @{
                            (id)kSecAttrAccount : encodedName,
                            (id)kSecAttrGeneric : encodedName,
                            (id)kSecAttrService : name,
                            (id)kSecClass : (id)kSecClassGenericPassword,
                            };
    NSDictionary *attributes = nil;
    if (attribute == kSecValueData) {
        attributes = @{ (id)kSecValueData : [value dataUsingEncoding:NSUTF8StringEncoding] };
    } else {
        attributes = @{ attribute : value };
    }

    OSStatus result = SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attributes);
}

使用作品设置值,[self updateKeychainItem:AuthTokenIdentifer value:authToken attribute:kSecValueData];我可以在钥匙串访问中看到它。

使用作品获取结果NSDictionary *values = [self getKeychainItem:AuthTokenIdentifer];,但未在字典中设置 kSecValueData。其他所有内容都已设置,例如创建和修改日期,而不是安全数据。

有任何想法吗?这发生在 iOS 和 Mac 上。

4

1 回答 1

0

您需要使用 getKeychainItem: 中的属性字典来获取值。就像是

NSMutableDictionary *dataQuery = [attrs mutableCopy];
[dataQuery setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
[dataQuery setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];

CFTypeRef resultData;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)(dataQuery), &resultData);
NSData *tokenData = CFBridgingRelease(resultData);
于 2014-06-03T14:28:16.240 回答