iOS--KeyChina 简单使用

今天了解一下KeyChina,之前保存的用户信息都放在NSUserDefaults,这样很不安全,现在写的话我会放在KeyChina中,因为他存储的信息还是比较安全的,Keychain的信息是存在于每个应用(app)的沙盒之外的,所以keychain里保存的信息不会因App被删除而丢失,在用户重新安装App后依然有效,数据还在。(就是将一些敏感信息,储存起来);

接下来我们来简单的集成一下吧,保存用户的账号和密码,还有其他用处,这里并没有介绍:

集成之前先说一下,KeyChina现在不支持ARC,所以需要我们手动的配置工程,在代码中会有体现,

首先导入系统的框架:

然后我们新建一个类:KeyChina;

.m:

#import <Foundation/Foundation.h>
#import <Security/Security.h>

@interface KeyChina : NSObject
/**
 *  用KeyChaina去保存用户名和密码
 */
+(void)save:(NSString *)service data:(id)data;
/**
 *  从KeyChina取出用户名和密码
 */
+(id)load:(NSString *)service;
/**
 *  从KeyChina中删除用户名和密码
 */
+ (void)delete:(NSString *)service;


@end

.h实现:

#import "KeyChina.h"
@implementation KeyChina

/**
 *  该类需要工作在mrc模式下,如果项目是arc,按照下面进行操作
 *  选中工程->TARGETS->相应的target然后选中右侧的“Build Phases”,向下就找到“Compile Sources”了。然后在相应的文件后面添加:-fno-objc-arc参数
 */

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

#pragma mark -- 写入
+(void)save:(NSString *)service data:(id)data{
    
    //Get search dictionary
    NSMutableDictionary *keyChinaQuery = [self getKeychinaQuery:service];
    //Delete old item before add new item
    SecItemDelete((CFDictionaryRef)keyChinaQuery);
    //Add new object to search dictionary(Attention:the data format)
    [keyChinaQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    //Add item to keychain with the search dictionary
    SecItemAdd((CFDictionaryRef)keyChinaQuery, NULL);
}
#pragma mark -- 读取
+ (id)load:(NSString *)service{
    
    id ret = nil;
    NSMutableDictionary *keychinaQuery = [self getKeychinaQuery: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
    [keychinaQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [keychinaQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((CFDictionaryRef)keychinaQuery, (CFTypeRef *)&keyData) == noErr) {
        @try {
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)keyData];
        } @catch (NSException *e) {
            NSLog(@"Unarchive of %@ failed: %@", service, e);
        } @finally {
        }
    }
    if (keyData)
        CFRelease(keyData);
        return ret;
    
}
#pragma mark -- 删除
+(void)delete:(NSString *)service{
    NSMutableDictionary *keychinaQuery = [self getKeychinaQuery:service];
    SecItemDelete((CFDictionaryRef)keychinaQuery);
}


@end

在需要的地方调用:

#import "ViewController.h"
#import "KeyChina.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSString * const KEY_USERNAME_PASSWORD = @"com.company.app.usernamepassword";
    NSString * const KEY_USERNAME = @"com.company.app.username";
    NSString * const KEY_PASSWORD = @"com.company.app.password";
    
    NSMutableDictionary *userNamePasswordKVPairs = [NSMutableDictionary dictionary];
    [userNamePasswordKVPairs setObject:@"userName" forKey:KEY_USERNAME];
    [userNamePasswordKVPairs setObject:@"password" forKey:KEY_PASSWORD];

    // A、将用户名和密码写入keychain
   [KeyChina save:KEY_USERNAME_PASSWORD data:userNamePasswordKVPairs];
    // B、从keychain中读取用户名和密码
    NSMutableDictionary *readUsernamePassword = (NSMutableDictionary *)[KeyChina load:KEY_USERNAME_PASSWORD];
    NSString *userName = [readUsernamePassword objectForKey:KEY_USERNAME];
    NSString *password = [readUsernamePassword objectForKey:KEY_PASSWORD];
    NSLog(@"username = %@", userName);
    NSLog(@"password = %@", password);
    
    // C、将用户名和密码从keychain中删除
    [KeyChina delete:KEY_USERNAME_PASSWORD];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    
}

@end

OK了!!!

原文地址:https://www.cnblogs.com/LzwBlog/p/5744135.html