持续化存储 --沙盒外

持续化存储 --沙盒外 Keychain

我们使用NSUserDefaults存储数据信息,但是对于一些私密信息,但是对于一下比较私密的信息,如帐号、密码等等,我们就需要使用更为安全的keychain了。keychain保存的信息是保存在沙盒之外的,不会因App的删除而丢失,在用户重新安装了App后依然存在。其实可以把keychain理解成一个Dictionary,所有数据都以key-value的形式存储,可以对这个Dictionary进行add、update、get、delete这四个操作。对一个应用来说,keychain都有两个访问区,私有和公共。

  1. Target - Capabilities - Keychain Sharing - ON

    图2.png

    左侧的目录会自动生成Entitlements文件,不需要自己创建了。

  2. 引入Security.framework

  3. 自定义一个类,取名keychain,如下:

.h

#import <Foundation/Foundation.h>
@interface keychain : NSObject
/**添加*/
+(void)savePassWord:(NSString *)password;
/**读取*/
+(id)loadPassWord;
/**删除*/
+(void)deletePassword;
@end
复制代码

.m文件

#import "keychain.h"
#import <Security/Security.h>

@implementation keychain
static NSString *const KEY_KEYCHAIN = @"LCF";
static NSString *const KEY_PASSWORD = @"PASSWORD";
/**添加*/
+(void)savePassWord:(NSString *)password{
    NSMutableDictionary *infoDict = [NSMutableDictionary dictionary];
    [infoDict setObject:password forKey:KEY_PASSWORD];
    [keychain save:KEY_KEYCHAIN data:infoDict];
}
/**读取*/
+(id)loadPassWord{
    NSMutableDictionary *infoDict = [keychain load:KEY_KEYCHAIN];
    return [infoDict objectForKey:KEY_PASSWORD];
}
/**删除*/
+(void)deletePassword{
    [self delete:KEY_KEYCHAIN];
}
+(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 attribute 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)delete:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
}
@end
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • keychain app官方链接 重要的事情说三遍 使用keychain group的时候,测试一定要使用真机! ...
    Rxiaobing阅读 3,269评论 1 5
  • Keychain与NSUserDefaults的比较 NSUserDefaults作用的场所: NSUserDef...
    Harely阅读 1,289评论 0 2
  • 首先这里的持久化指的是数据持久化,目前客户端的持久化也只有这一个含义。 为何要持久化: iOS开发可以没有持久化,...
    Hyyqinfen阅读 268评论 0 1
  • 简介 持久化就是将数据保存到硬盘中,让APP重启后可以使用之前保存的数据.在iOS开发中,可能会用到一下几种 pl...
    carpond阅读 717评论 0 1
  • NSUserDefaults An interface to the user’s defaults databa...
    奚山遇白阅读 1,458评论 0 0