前段時間卸載了QQ审轮,之后又重新安裝了肥哎,奇怪的是賬號和密碼信息竟然還在辽俗,就覺得好奇怪,百度了一波篡诽,挖出了KeyChain崖飘。下面給大家分享一下我的認(rèn)知和它的簡單使用,有不同見解的歡迎提出杈女。
a)什么是鑰匙串朱浴?
KeyChain在Mac上大家都比較熟悉,主要進(jìn)行一些敏感信息存儲使用如用戶名达椰,密碼翰蠢,網(wǎng)絡(luò)密碼,認(rèn)證令牌啰劲,Wi-Fi網(wǎng)絡(luò)密碼梁沧,VPN憑證等。iOS中鑰匙扣蝇裤,也有相同的功能實現(xiàn)廷支,保存的信息存儲在設(shè)備中,獨立于每個App沙盒之外猖辫。作者這篇就簡單整理下iOS中的鑰匙扣酥泞。
特點:
1。相對于NSUserDefault存儲一些數(shù)據(jù)啃憎,會更加安全。
2似炎。即便App被卸載辛萍,存儲的信息依舊存在,再次安裝App羡藐,存儲是信息依舊可以使用贩毕。
3。相同的團(tuán)隊ID開發(fā)仆嗦,可實現(xiàn)多個應(yīng)用共享數(shù)據(jù)辉阶。
b)結(jié)構(gòu)
KeyChain和NSUserDefault 的結(jié)構(gòu)類似,也是一個個鍵值對key-value相互映射組成的瘩扼。
在iOS中每個APP 都有屬于自己的KeyChain谆甜,最常用就是保存用戶的賬戶和密碼,就是記住密碼集绰,放在這里很安全规辱,蘋果負(fù)責(zé)幫我們加密再存起來,假如用NSUserDefault 保存這些秘密數(shù)據(jù),生成的plist文件容易被拿到(----->Library/Preferences),而且還要自己做加密栽燕。
(說實話罕袋,結(jié)構(gòu)這方面的理解還沒達(dá)到能表達(dá)的很詳細(xì)的地步改淑,所以暫時只share這么一些,有更好的見解的歡迎指教T⊙丁)
c) 使用
KeyChain 主要的用法也就是添加朵夏,刪除,修改榆纽,查詢仰猖。這里我自己做了個簡單的封裝,歡迎大家使用掠河,話不多說亮元,直接上代碼。
ATKeyChain.h
#import <Foundation/Foundation.h>
@interfaceATKeyChain :NSObject
#pragma mark存儲用戶偏好設(shè)置到NSUserDefults
+(void)saveUserData:(id)data forKey:(NSString*)key;
#pragma mark讀取用戶偏好設(shè)置
+(id)readUserDataForKey:(NSString*)key;
#pragma mark刪除用戶偏好設(shè)置
+(void)removeUserDataForkey:(NSString*)key;
@end
ATKeyChain.m
#import "ATKeyChain.h"
@implementation ATKeyChain
#pragma mark ----public method
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)key {
return [NSMutableDictionary dictionaryWithObjectsAndKeys:(id)kSecClassGenericPassword,(id)kSecClass,
key, (id)kSecAttrService,
key, (id)kSecAttrAccount,
(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
nil];
}
#pragma mark ----寫入
// 說明: 該封裝 添加與更新 為同一方法, 不進(jìn)行判斷, 直接先刪除后添加
+(void)saveUserData:(id)data forKey:(NSString*)key{
NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
SecItemDelete((CFDictionaryRef)keychainQuery);
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}
#pragma mark ----讀取
+(id)readUserDataForKey:(NSString*)key; {
id data = nil;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
[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 {
data = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
} @catch (NSException *e) {
NSLog(@"Unarchive of %@ failed: %@", key, e);
} @finally {
}
}
if (keyData)
CFRelease(keyData);
return data;
}
#pragma mark ----刪除
+(void)removeUserDataForkey:(NSString*)key{
NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
SecItemDelete((CFDictionaryRef)keychainQuery);
}
@end
調(diào)用
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
[userInfo setObject:@"Mars_pananting" forKey:@"userName"];
[userInfo setObject:@"12345678" forKey:@"password"];
//添加
[ATKeyChain saveUserData:userInfo forKey:@"userInfo"];
//讀取
NSMutableDictionary *result =[ATKeyChain readUserDataForKey:@"userInfo"];
NSLog(@"result ==%@",result);
//移除
[ATKeyChain removeUserDataForkey:@"userInfo"];
好了唠摹,以上我就是我對KeyChain 的簡單總結(jié)爆捞。希望能給大家?guī)韼椭?/p>