美文网首页
持续化存储 --沙盒外

持续化存储 --沙盒外

作者: 小手凉凉 | 来源:发表于2019-03-19 11:30 被阅读0次

    持续化存储 --沙盒外 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
    

    相关文章

      网友评论

          本文标题:持续化存储 --沙盒外

          本文链接:https://www.haomeiwen.com/subject/gicgmqtx.html