Keychain簡(jiǎn)單理解和使用

app里的登錄模塊就是保存登錄過(guò)用戶名和密碼捅位,如果用戶選擇記住密碼則保存最長(zhǎng)保存7天,這樣用戶下次登錄app的時(shí)候搂抒,就可以直接登錄了艇搀,或者輸入已經(jīng)登錄過(guò)的帳號(hào)時(shí),自動(dòng)填充密碼求晶。之前由于時(shí)間趕焰雕,用的NSUserDefaults 進(jìn)行保存的用戶名,密碼芳杏,時(shí)間明文保存的矩屁,估計(jì)這個(gè)讓老板知道會(huì)打死我,其實(shí)自己想想也覺(jué)得后背發(fā)涼爵赵。今天剛好有時(shí)間發(fā)現(xiàn)Keychain正好可以滿足這個(gè)需求吝秕。

Keychain是一塊相對(duì)獨(dú)立的空間,當(dāng)app升級(jí)時(shí)亚再,已保存在Keychain里的信息不會(huì)被刪除掉郭膛。Keychain的數(shù)據(jù)即使被別人拿到也由于是加密的,無(wú)法看到Keychain里的數(shù)據(jù)氛悬。因此比較適合用來(lái)存儲(chǔ)用戶的一些機(jī)密信息则剃。

Keychain里主要方法有四個(gè):

  1. OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result)

  2. OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result)

  3. OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)

  4. OSStatus SecItemDelete(CFDictionaryRef query)

SecItemAdd表示往Keychain 里增加一條數(shù)據(jù),第一個(gè)參數(shù)表示數(shù)據(jù)如捅,第二個(gè)參數(shù)表示執(zhí)行該操作后棍现,指向剛添加的這個(gè)數(shù)據(jù)的引用,如果不需要用到這條數(shù)據(jù)镜遣,可以傳入NULL(翻譯自apple文檔)己肮。

SecItemCopyMatching表示查詢Keychain里是否有符號(hào)條件的記錄士袄。第一個(gè)參數(shù)查詢條件,第二個(gè)查詢到結(jié)果的引用谎僻。

SecItemUpdate更新Keychain里的記錄娄柳。第一個(gè)參數(shù)表示查詢條件,第二個(gè)表示當(dāng)根據(jù)第一個(gè)查詢條件后艘绍,用于更新的值赤拒。

SecItemDelete刪除符號(hào)查詢條件的記錄。參數(shù)表示查詢條件

總結(jié)就是增诱鞠,查挎挖,改,刪航夺。

結(jié)合代碼說(shuō)明怎么用比較好(實(shí)現(xiàn)代碼模仿網(wǎng)上的一個(gè)做法)蕉朵。

QPKeychain.h

@interface QPKeychain :NSObject

+ (void)save:(NSString*)key data:(id)data;

+ (id)load:(NSString*)key;

+ (void)remove:(NSString*)key;

@end

QPKeychain.m文件

#import "QPKeychain.h"

#import@implementation QPKeychain

+ (NSMutableDictionary *)getKeychainQuery:(NSString *)key {

return [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)kSecClassGenericPassword, (__bridge id)kSecClass,

key, (__bridge id)kSecAttrService, key, (__bridge id)kSecAttrAccount, (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible, nil];

}

+ (void)save:(NSString *)key data:(id)data {

NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];

SecItemDelete((__bridge CFDictionaryRef)keychainQuery);

[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];

SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);

}

+ (id)load:(NSString *)key {

id ret = nil;

NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];

[keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];

[keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];

CFDataRef keyData = NULL;

if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {

@try {

ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];

} @catch (NSException *e) {

//            NSLog(@"Unarchive of %@ failed: %@", key, e);

} @finally {

}

}

if (keyData) {

CFRelease(keyData);

}

return ret;

}

+ (void)remove:(NSString *)key {

NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];

SecItemDelete((__bridge CFDictionaryRef)keychainQuery);

}

@end

實(shí)際上就是3個(gè)功能,保存阳掐,讀取始衅,刪除keychain。

  • (NSMutableDictionary)getKeychainQuery:(NSString)key方法生成一個(gè)字典锚烦,該字典包含了一條keychain item的設(shè)置觅闽。kSecClass 表示該條item是什么類型的,kSecClassGenericPassword表示一般密碼類型的item(還有幾個(gè)其他類型的涮俄,猜測(cè)這些類型會(huì)采用不同的加密級(jí)別)。kSecAttrService用于描述該item的service屬性(具體用于干什么尸闸,還不太清楚)彻亲。kSecAttrAccount指定item的account name。kSecAttrAccessible顧名思義就是設(shè)置item的屬性訪問(wèn)方式的吮廉,kSecAttrAccessibleAfterFirstUnlock表示只要設(shè)備一旦設(shè)備啟動(dòng)解鎖后就可以一直訪問(wèn)苞尝。

  • (void)save:(NSString*)key data:(id)data方法將鍵值key,數(shù)據(jù)data存放如item中宦芦。先將keychain里的account name為key的刪除掉宙址,然后再插入(這2步等價(jià)于SecItemUpdate)

  • (id)load:(NSString*)key方法查找account name 為key的item,然后將查到的item返回调卑。其中用到了SecItemCopyMatching函數(shù)抡砂。

  • (void)remove:(NSString*)key方法將account name 的item刪除掉。

這樣對(duì)于那個(gè)保存用戶名恬涧,密碼的功能就可以很簡(jiǎn)單的實(shí)現(xiàn)了注益。將用戶名,密碼溯捆,有效的登錄時(shí)間存入一個(gè)字典里丑搔,然后以用戶名為account name,字典為data存入到keychain中。子UITextField的valueDidChanged,textFieldShouldReturn回調(diào)中以用戶當(dāng)前的輸入去獲取密碼來(lái)填充密碼輸入框啤月,代碼如下:

+ (void)fillPasswordTFWithUserNameTF:(UITextField *)userNameTF withPasswordTF:(UITextField *)passwordTF {

NSString *account = userNameTF.text;

NSMutableDictionary *userInfos = [QPKeychain load:account];//獲取keychain里的用戶煮仇,密碼等信息

if (userInfos == nil) {

passwordTF.text = @"";

} else {

double now = [[[NSDate alloc] init] timeIntervalSince1970];

double time = [[userInfos objectForKey:LOGIN_USER_DATE] doubleValue];

if ((now - time) / (24 * 3600) < 7) {//7天有效

NSString *password = [userInfos objectForKey:LOGIN_USER_PASSWORD];

passwordTF.text = password;

} else {

passwordTF.text = @"";

}

}

}

由于水平有限,也沒(méi)時(shí)間去深入研究keychain的具體實(shí)現(xiàn)谎仲,只能點(diǎn)到為止了欺抗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市强重,隨后出現(xiàn)的幾起案子绞呈,更是在濱河造成了極大的恐慌,老刑警劉巖间景,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佃声,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡倘要,警方通過(guò)查閱死者的電腦和手機(jī)圾亏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)封拧,“玉大人志鹃,你說(shuō)我怎么就攤上這事≡笪鳎” “怎么了曹铃?”我有些...
    開(kāi)封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)捧杉。 經(jīng)常有香客問(wèn)我陕见,道長(zhǎng),這世上最難降的妖魔是什么味抖? 我笑而不...
    開(kāi)封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任评甜,我火速辦了婚禮,結(jié)果婚禮上仔涩,老公的妹妹穿的比我還像新娘忍坷。我一直安慰自己,他們只是感情好熔脂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布佩研。 她就那樣靜靜地躺著,像睡著了一般锤悄。 火紅的嫁衣襯著肌膚如雪韧骗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天零聚,我揣著相機(jī)與錄音袍暴,去河邊找鬼些侍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛政模,可吹牛的內(nèi)容都是我干的岗宣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼淋样,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼耗式!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起趁猴,我...
    開(kāi)封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤刊咳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后儡司,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體娱挨,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年捕犬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了跷坝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碉碉,死狀恐怖柴钻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情垢粮,我是刑警寧澤贴届,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站足丢,受9級(jí)特大地震影響粱腻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜斩跌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捞慌。 院中可真熱鬧耀鸦,春花似錦、人聲如沸啸澡。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嗅虏。三九已至洛姑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間皮服,已是汗流浹背楞艾。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工参咙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人硫眯。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓蕴侧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親两入。 傳聞我的和親對(duì)象是個(gè)殘疾皇子净宵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容