今天了解一下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了!!!
时间: 2024-09-29 05:06:08