2016.12.22最新更新
最近一直有朋友說不知道怎么用,特來更新了 PDKeyChain,添加了注釋嘲恍,有問題可以提 issue 歡迎討論。
2016.8.23最新更新
最近一直有朋友問源碼雄驹,整理了一下發(fā)在這里佃牛。
2016.3.23最新更新
近期項目中又用到keychain,于是回頭翻了翻以前寫的代碼医舆,感覺寫的/(ㄒoㄒ)/~~
設計不科學俘侠,命名不規(guī)范象缀,怎么看怎么別扭,那就重寫吧~
Tips:在實習過程中爷速,有次讓我實現(xiàn)一個app七天免登陸功能央星。當時沒細想,直接就用NSUserDefaults給做的惫东,用NSDate判斷時間莉给,取七天的間隔判斷登陸狀態(tài)。直到現(xiàn)在了解了keychain廉沮,才知道用NSUserDefaults是非常不安全的颓遏。通常情況下,可以用NSUserDefaults存儲數(shù)據(jù)信息滞时,但是對于一些私密信息叁幢,比如賬號、密碼等等坪稽,就需要使用更為安全的keychain了曼玩。而Keychain的信息是存在于每個應用(app)的沙盒之外的,所以keychain里保存的信息不會因App被刪除而丟失窒百,在用戶重新安裝App后依然有效黍判,數(shù)據(jù)還在。
KeyChain
話不多說贝咙,咱們直接來看怎么快速集成keychain样悟。
- 自定義一個類拂募,取名XXXKeyChain庭猩,如下:
#import <Foundation/Foundation.h>
#import <Security/Security.h>
#define KEY_PASSWORD @"com.rry.app.password"
#define KEY_USERNAME_PASSWORD @"com.rry.app.usernamepassword"
@interface RRYKeyChain : NSObject
+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)delete:(NSString *)service;
@end
以上代碼自定義了三個方法,存陈症、取蔼水、刪。并且定義了幾個字符串用來做key录肯。當然趴腋,想使用keychain請不要忘記引入Security包,引入文件 #import <Security/Security.h>论咏。
- 再來看.m文件的具體實現(xiàn)
#import "RRYKeyChain.h"
@implementation RRYKeyChain
+ (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:(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);
}
然后就是存优炬,其中mmm是要存的密碼字符串。
NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionary];
[usernamepasswordKVPairs setObject:mmm forKey:KEY_PASSWORD];
[RRYKeyChain save:KEY_USERNAME_PASSWORD data:usernamepasswordKVPairs];
取
NSMutableDictionary *usernamepasswordKVPairs = (NSMutableDictionary *)[RRYKeyChain load:KEY_USERNAME_PASSWORD];
NSLog(@"%@",[usernamepasswordKVPairs objectForKey:KEY_PASSWORD]);
刪
[RRYKeyChain delete:KEY_USERNAME_PASSWORD];
這樣一個簡單的使用keychain快速存儲密碼的功能就做好了厅贪。
2016.3.23最新更新
話不多說蠢护,直接上代碼,首先是.h
#import <Foundation/Foundation.h>
#import <Security/Security.h>
@interface RHKeyChain : NSObject
+ (void)rhKeyChainSave:(NSString *)service;
+ (NSString *)rhKeyChainLoad;
+ (void)rhKeyChainDelete:(NSString *)service;
@end
只對外提供三個方法养涮,存葵硕、取眉抬、刪,實現(xiàn)放在內部懈凹,再是.m
static NSString * const kRHDictionaryKey = @"com.xxxx.dictionaryKey";
static NSString * const kRHKeyChainKey = @"com.xxxx.keychainKey";
+ (void)rhKeyChainSave:(NSString *)service {
NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
[tempDic setObject:service forKey:kRHDictionaryKey];
[self save:kRHKeyChainKey data:tempDic];
}
+ (NSString *)rhKeyChainLoad{
NSMutableDictionary *tempDic = (NSMutableDictionary *)[self load:kRHKeyChainKey];
return [tempDic objectForKey:kRHDictionaryKey];
}
+ (void)rhKeyChainDelete{
[self delete:kRHKeyChainKey];
}
三個方法的實現(xiàn)蜀变。