
iOS的keyChain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keyChain存储。相对于NSUserDefaults、文件保存等一般方式,keyChain保存更为安全,而且keyChain里保存的信息不会因App被删除而丢失,所以在重装App后,keychain里的数据还能使用,只有刷机或者越狱才对其中的数据有影响.
思路如下:
1,安装 APP 后自动生成一个 UUID
2,检查keyChain中是否有相应关键字的 UUID,如果没有存储,反之不存储.
3,keychain里的数据还能使用,只有刷机或者越狱才对其中的数据有影响.
所以可以很有效保证设备唯一性需求.
代码如下:(封装 keyChain 的方法)
. h
//// KeyChainManager.h// ChartDemo//// Created by user on 2017/9/27.// Copyright © 2017年 MK. All rights reserved.//#import <Foundation/Foundation.h>@interface KeyChainManager : NSObject+ (NSString *)isExistUUID;/**添加 UUID@param uuid 添加的对象*/+ (void ) addObject:(NSString *)uuid ;/**删除 UUID*/+ (void ) removeObject;@end
.m
//// KeyChainManager.m// ChartDemo//// Created by user on 2017/9/27.// Copyright © 2017年 MK. All rights reserved.//#import "KeyChainManager.h"#import <Security/Security.h>@implementation KeyChainManagerstatic NSString * const MY_UUIDDictionaryKEY = @"com.MK.ChartDemo";static NSString * const MY_UUIDKEY = @"com.MK.ChartDemoKey";+ (NSString *)isExistUUID{NSString * uuid = (NSString *)[self showUUID];NSLog(@"UUid : %@", uuid);return uuid;}+ (void) addObject:(NSString *)uuid{if (uuid) {NSMutableDictionary * dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:uuid,MY_UUIDDictionaryKEY, nil];NSMutableDictionary * query = [self getKeyChainQuery:MY_UUIDKEY];if (query) {SecItemDelete((CFDictionaryRef)query);[query setObject:[NSKeyedArchiver archivedDataWithRootObject:dict] forKey:(id)kSecValueData];SecItemAdd((CFDictionaryRef)query, NULL);}}}+ (void)removeObject{SecItemDelete((CFDictionaryRef)[self getKeyChainQuery:MY_UUIDKEY]);}+ (id)showUUID{id selectObject = nil;NSMutableDictionary * query = [self getKeyChainQuery:MY_UUIDKEY];[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];[query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];CFDataRef data = NULL;if (SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&data) == noErr) {@try{selectObject = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)data];}@catch (NSException * e){NSLog(@"解包异常 %@ : %@", query, e);}@finally{}}if (data) {CFRelease(data);}if (selectObject) {return [((NSDictionary *)selectObject) objectForKey:MY_UUIDDictionaryKEY];}return nil;}/**获取KeyChain的查询@param key 关键字@return 获得查询的 ref*/+ (NSMutableDictionary *) getKeyChainQuery:(NSString *) key{return [NSMutableDictionary dictionaryWithObjectsAndKeys:(id)kSecClassGenericPassword,(id)kSecClass,key, (id)kSecAttrService,key, (id)kSecAttrAccount,(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,nil];}@end
AppDelegate中的调用:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {// Override point for customization after application launch.if (![KeyChainManager isExistUUID]) {[KeyChainManager addObject:[[NSUUID UUID] UUIDString]];}return YES;}
