Saving Email/Password to Keychain in iOS

后端 未结 2 1348
鱼传尺愫
鱼传尺愫 2020-11-28 01:16

I\'m very new to iOS development so forgive me if this is a newbie question. I have a simple authentication mechanism for my app that takes a user\'s email address and pass

2条回答
  •  -上瘾入骨i
    2020-11-28 01:36

    ARC ready code:

    KeychainUserPass.h

    #import 
    
    @interface KeychainUserPass : NSObject
    
    + (void)save:(NSString *)service data:(id)data;
    + (id)load:(NSString *)service;
    + (void)delete:(NSString *)service;
    
    @end
    

    KeychainUserPass.m

    #import "KeychainUserPass.h"
    
    @implementation KeychainUserPass
    
    + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
        return [NSMutableDictionary dictionaryWithObjectsAndKeys:
                (__bridge id)kSecClassGenericPassword, (__bridge id)kSecClass,
                service, (__bridge id)kSecAttrService,
                service, (__bridge id)kSecAttrAccount,
                (__bridge id)kSecAttrAccessibleAfterFirstUnlock, (__bridge id)kSecAttrAccessible,
                nil];
    }
    
    + (void)save:(NSString *)service data:(id)data {
        NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
        SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
        [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];
        SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
    }
    
    + (id)load:(NSString *)service {
        id ret = nil;
        NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
        [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
        [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
        CFDataRef keyData = NULL;
        if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
            @try {
                ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
            }
            @catch (NSException *e) {
                NSLog(@"Unarchive of %@ failed: %@", service, e);
            }
            @finally {}
        }
        if (keyData) CFRelease(keyData);
        return ret;
    }
    
    + (void)delete:(NSString *)service {
        NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
        SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    }
    
    @end
    

提交回复
热议问题