苹果提供Keychain存储方案在Security.framework,里面还有很多关于证书方面的内容,有兴趣的可以研究下。
其中Secitem.h供定义了四个方法:
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
OSStatus SecItemUpdate(CFDictionaryRef query,
CFDictionaryRef attributesToUpdate)
OSStatus SecItemDelete(CFDictionaryRef query)
相应的在封装时也需提供。下面直接贴代码:
GTRKeyChainStore.h
#import
@interface GTRKeyChainStore : NSObject
@property (nonatomic, strong) NSString *uuid;
@property (nonatomic, strong) NSString *userName;
@property (nonatomic, strong) NSString *pwd;
@end
GTRKeyChainStore.m
#import "GTRKeyChainStore.h"
@implementation GTRKeyChainStore
- (NSString *)prefixBundleID {
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
return bundleId ? bundleId:@"com.gtr.demo";
}
- (void)setUserName:(NSString *)userName {
[self setKeyChainValue:userName forKey:[NSString stringWithFormat:@"%@username",[self prefixBundleID]]];
}
- (NSString *)userName {
return [self getKeyChainValueForKey:[NSString stringWithFormat:@"%@username",[self prefixBundleID]]];
}
- (void)setPwd:(NSString *)pwd {
[self setKeyChainValue:pwd forKey:[NSString stringWithFormat:@"%@pwd",[self prefixBundleID]]];
}
- (NSString *)pwd {
return [self getKeyChainValueForKey:[NSString stringWithFormat:@"%@pwd",[self prefixBundleID]]];
}
- (void)setUuid:(NSString *)uuid {
[self setKeyChainValue:uuid forKey:[NSString stringWithFormat:@"%@uuid",[self prefixBundleID]]];
}
- (NSString *)uuid {
return [self getKeyChainValueForKey:[NSString stringWithFormat:@"%@uuid",[self prefixBundleID]]];
}
- (BOOL)setKeyChainValue:(NSString *)valueString forKey:(NSString *)keyString {
if (!valueString) {
[self deleteItemFromKeyChainWithIdentifier:keyString];
return YES;
}
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
NSData *valueData = [valueString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: bundleId,
(__bridge id)kSecAttrGeneric: keyData,
(__bridge id)kSecAttrAccount: keyData,
(__bridge id)kSecValueData: valueData,
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenUnlocked
};
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
if (errSecSuccess == status) {
return YES;
} else if (errSecDuplicateItem == status) {
return [self updateKeyChainValue:valueString forKey:keyString];
} else {
return NO;
}
}
- (BOOL)updateKeyChainValue:(NSString *)valueString forKey:(NSString *)keyString {
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
NSData *valueData = [valueString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: bundleId,
(__bridge id)kSecAttrGeneric: keyData,
(__bridge id)kSecAttrAccount: keyData
};
NSDictionary *dataDict = @{
(__bridge id)kSecValueData: valueData
};
OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)dict, (__bridge CFDictionaryRef)dataDict);
if (errSecSuccess == status) {
return YES;
} else {
return NO;
}
}
- (NSString *)getKeyChainValueForKey:(NSString *)keyString {
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: bundleId,
(__bridge id)kSecAttrGeneric: keyData,
(__bridge id)kSecAttrAccount: keyData,
(__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne,
(__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue
};
CFTypeRef found = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)dict, &found);
if (noErr == status) {
NSData *result = (__bridge_transfer NSData *)found;
return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
} else {
return nil;
}
}
- (void)deleteItemFromKeyChainWithIdentifier:(NSString *)identifier {
NSDictionary *searchDict = [self setupSearchDictionaryForIdentifier:identifier];;
CFDictionaryRef dict = (__bridge CFDictionaryRef)searchDict;
SecItemDelete(dict);
}
- (NSDictionary *)setupSearchDictionaryForIdentifier:(NSString *)identifier {
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
NSMutableDictionary *searchDict = [NSMutableDictionary dictionary];
[searchDict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[searchDict setObject:bundleId forKey:(__bridge id)kSecAttrService];
NSData *keyData = [identifier dataUsingEncoding:NSUTF8StringEncoding];
[searchDict setObject:keyData forKey:(__bridge id)kSecAttrGeneric];
[searchDict setObject:keyData forKey:(__bridge id)kSecAttrAccount];
return searchDict;
}
@end
测试代码
GTRKeyChainStore *store = [[GTRKeyChainStore alloc] init];
// store.userName = @"gtr";
// store.pwd = @"meiyoumima";
// NSString *uuid = [NSString randomUUID];
// if (uuid) {
// store.uuid = uuid;
// } else if ((uuid = [NSString appleIFA])) {
// store.uuid = uuid;
// } else {
// store.uuid = [NSString appleIFV];
// }
NSLog(@"gtr username:%@",store.userName);
NSLog(@"gtr username:%@",store.pwd);
NSLog(@"gtr username:%@",store.uuid);
功能代码
+ (NSString *)appleIFA {
NSString *ifa = nil;
Class ASIdentifierManagerClass = NSClassFromString(@"ASIdentifierManager");
if (ASIdentifierManagerClass) {
SEL sharedManagerSelector = NSSelectorFromString(@"sharedManager");
id sharedManager = ((id (*)(id, SEL))[ASIdentifierManagerClass methodForSelector:sharedManagerSelector])(ASIdentifierManagerClass, sharedManagerSelector);
SEL advertisingIdentifierSelector = NSSelectorFromString(@"advertisingIdentifier");
NSUUID *advertisingIdentifier = ((NSUUID* (*)(id, SEL))[sharedManager methodForSelector:advertisingIdentifierSelector])(sharedManager, advertisingIdentifierSelector);
ifa = [advertisingIdentifier UUIDString];
}
return ifa;
}
+ (NSString *)appleIFV {
if(NSClassFromString(@"UIDevice") && [UIDevice instancesRespondToSelector:@selector(identifierForVendor)]) {
return [[UIDevice currentDevice].identifierForVendor UUIDString];
}
return nil;
}
+ (NSString *)randomUUID {
if(NSClassFromString(@"NSUUID")) {
return [[NSUUID UUID] UUIDString];
}
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef cfuuid = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
CFRelease(uuidRef);
NSString *uuid = [((__bridge NSString *) cfuuid) copy];
CFRelease(cfuuid);
return uuid;
}
直接复制黏贴可用。