KeyChain钥匙串的使用

作者: LuxDark | 来源:发表于2016-04-20 10:39 被阅读559次

    相信在我们存储一些数据的时候都会遇到一些苦恼,如果应用一旦被用户删除,那么设备中的信息就会被清除掉。此时,keychain就发挥了作用,当应用被用户删除掉时,保存在keychain中的数据还会存在,除非用户重装系统。那么我们就简单说明下keychain的使用吧!

    一、以保存密码为例:
    + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
    (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
    service, (__bridge_transfer id)kSecAttrService,
    service, (__bridge_transfer id)kSecAttrAccount,
    (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,
    nil];
    }

    1.保存数据:
    + (void)save:(NSString *)service data:(id)data {

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

    2.取数据:
    + (id)load:(NSString *)service {
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    //Configure the search setting
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];
    [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit];
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
    @try {
    ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];
    } @catch (NSException *e) {
    NSLog(@"Unarchive of %@ failed: %@", service, e);
    } @finally {
    }
    }
    return ret;
    }

    3.删除数据:
    + (void)delete:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
    }

    二、在控制器中使用(我把上面的方法封装在了YNKeyChain这个类里面方便使用):

    static NSString * const KEY_PASSWORD = @"ynwang.app.password";
    
    //保存
    - (IBAction)saveAction:(id)sender {
    
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    [dictionary setObject:self.passwordTextField.text forKey:KEY_PASSWORD];
    [YNKeyChain save:KEY_PASSWORD data:dictionary];
    }
    
    //删除
    - (IBAction)deleteAction:(id)sender {
    [YNKeyChain delete:KEY_PASSWORD];
    }
    
    //取数据
    - (IBAction)showPasswordAction:(id)sender {
    NSDictionary *dic = [YNKeyChain load:KEY_PASSWORD];
    if (dic) {
        self.passwordLabel.text = dic[KEY_PASSWORD];
    }
    else{
        self.passwordLabel.text = @"空";
    }
    }
    

    三、运行结果:

    E4D6B10E-0A0F-4F1A-8F07-63924C3C57AB.png

    四、keychain的另一个重要的作用,就是可以共享同一个开发者账号的不同APP之间的信息,这样就实现了两个不同应用之间信息的共享。主要有两个步骤。

    1.在APP target的bulib Setting里面添加Code Signing Entitlements为包含AceessGroup的分组信息的plist文件,否则会出现找不到文件的错误。如下图:

    A0448773-2902-4C5C-83B2-349ECBBBC519.png

    2.新建一个名字为Code Signing Entitlements中的plist文件,注意该文件的结构中最顶层的节点必须是一个名为“keychain-access-groups”的Array,并且该Array中每一项都是一个描述分组的NSString。对于String的格式也有相应要求,格式为:"AppIdentifier.com.*",其中AppIdentifier就是你的开发者帐号对应的ID。

    C70C1C21-68CF-46BE-9E8F-9803F87C7E0C.png

    原文链接:http://www.jianshu.com/p/ec8cab4bc0a4著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
    以上为keychain的简单使用,感谢会飞的咸鱼提供的文章参考。后续会继续更新,希望对大家有用。

    相关文章

      网友评论

      本文标题:KeyChain钥匙串的使用

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