iOS KeyChain(钥匙串)介绍

本文主要介绍使用KeyChain保存和获取APP数据,解决iOS上获取不变UDID的问题。并给出一个获取UDID的工具类,使用方便。

KeyChain介绍

iOS中的KeyChain相比OS X比较简单,整个系统只有一个KeyChain,每个程序都可以往KeyChain中记录数据,而且只能读取到自己程序记录在KeyChain中的数据。iOS中Security.framework框架提供了四个主要的方法来操作KeyChain:

// 查询
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result);

// 添加
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result);

// 更新KeyChain中的Item
OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);

// 删除KeyChain中的Item
OSStatus SecItemDelete(CFDictionaryRef query)

这四个方法参数比较复杂,一旦传错就会导致操作KeyChain失败,这块儿文档中介绍的比较详细,大家可以查查官方文档Keychain Services Reference。
  前面提到了每个APP只允许访问自己在KeyChain中记录的数据,那么是不是就没有别的办法访问其他APP存在KeyChain的数据了?​
  苹果提供了一个方法允许同一个发商的多个APP访问各APP之间的途径,即在调SecItemAdd添加数据的时候指定AccessGroup,即访问组。一个APP可以同时属于多个分组,添加KeyChain数据访问组等一些列的内容不在此赘述,本文主要讲解iOS上获取不变UDID的问题。

使用KeyChain保存和获取UDID

YXYKeyChainManager.h

//
//  YXYKeyChainManager.h
//  PrivilegeGo
//
//  Created by YXY on 2017/7/13.
//  Copyright © 2017年 Techwis. All rights reserved.
//

#import 

@interface YXYKeyChainManager : NSObject
// 存储
+ (void)save:(NSString *)service data:(id)data;
// 查询
+ (id)load:(NSString *)service;
// 删除
+ (void)deleteKeyData:(NSString *)service;

@end

YXYKeyChainManager.m

//
//  YXYKeyChainManager.m
//  PrivilegeGo
//
//  Created by YXY on 2017/7/13.
//  Copyright © 2017年 Techwis. All rights reserved.
//

#import "YXYKeyChainManager.h"

@implementation YXYKeyChainManager

+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
return [NSMutableDictionary dictionaryWithObjectsAndKeys:
        (id)kSecClassGenericPassword,(id)kSecClass,
        service, (id)kSecAttrService,
        service, (id)kSecAttrAccount,
        (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
        nil];
}

+ (void)save:(NSString *)service data:(id)data {
    //Get search dictionary
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    //Delete old item before add new item
     SecItemDelete((CFDictionaryRef)keychainQuery);
    //Add new object to search dictionary(Attention:the data format)
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    //Add item to keychain with the search dictionary
    SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}

+ (id)load:(NSString *)service {
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    //Configure the search setting
    //Since in our simple case we are expecting only a single at    tribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((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)deleteKeyData:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
}

@end

你可能感兴趣的:(iOS KeyChain(钥匙串)介绍)