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 KeyChainManager
static 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;
}