標籤:
今天瞭解一下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了!!!
iOS--KeyChina 簡單使用