iOS 钥匙串的基本使用
級(jí)別: ★☆☆☆☆
標(biāo)簽:「鑰匙串」「keychain」「iOS」
作者:?WYW
審校: QiShare團(tuán)隊(duì)
前言 :
項(xiàng)目中有時(shí)會(huì)需要存儲(chǔ)敏感信息(如密碼、密鑰等),蘋果官方提供了一種存儲(chǔ)機(jī)制--鑰匙串(keychain)。
keychain是一種存儲(chǔ)在硬盤上的加密的數(shù)據(jù)庫。這個(gè)可能是卸載App后,keychain信息還在的原因。
keychain適合存儲(chǔ) 較小的數(shù)據(jù)量(不超過上千字節(jié)或上兆字節(jié))的內(nèi)容。
筆者做了一個(gè)關(guān)于keychain的增、刪、改、查的Demo(QiKeychain),給大家介紹下keychain的基本使用。
下圖(確保keychain中用戶的信息安全)有利于我們直觀了解keychain。
Demo(QiKeychain)解讀:
筆者用Demo(QiKeychain)做了4件事。
- 增加:存儲(chǔ)用戶名、密碼到keychain;
- 查詢:根據(jù)用戶名從keychain中查詢密碼;
- 刪除:從keychain中刪除用戶名、密碼等相應(yīng)信息;
- 修改:修改keychain中的用戶名對(duì)應(yīng)的密碼;
Demo(QiKeychain)對(duì)keychain的操作效果如下:
- 存儲(chǔ)用戶名 “QiShare”,密碼:1234;
- 查詢用戶名為“QiShare”的密碼,顯示密碼為:1234;
- 修改用戶名“QiShare”的密碼為“123456”;
- 查詢“QiShare”的密碼,顯示為“123456”;
- 把“QiShare”從keychain中刪除。
keychain基本使用API
keychain有四個(gè)常用的API,用于增、刪、改、查keychain中的數(shù)據(jù)。
keychain中的數(shù)據(jù)子項(xiàng)是以item的形式存在的。
舉個(gè)例子:就存儲(chǔ)用戶名、密碼的情景來說,每個(gè)item包含存儲(chǔ)的用戶名和密碼及其他屬性信息,keychain中包含多個(gè)用戶名和密碼的item。
下圖(把數(shù)據(jù)和屬性存儲(chǔ)到keychain中)利于我們理解存儲(chǔ)過程
SecItemAdd:添加一個(gè)item或多個(gè)items到keychain
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)API_AVAILABLE(macos(10.6), ios(2.0)); 復(fù)制代碼存儲(chǔ)關(guān)鍵代碼:
NSDictionary *saveSecItems = @{(id)kSecClass: (id)kSecClassGenericPassword,(id)kSecAttrService: service,(id)kSecAttrAccount: account,(id)kSecValueData: passwordData};OSStatus saveStatus = SecItemAdd((CFDictionaryRef)saveSecItems, NULL); 復(fù)制代碼SecItemCopyMatching:返回匹配搜索查詢的一個(gè)item或多個(gè)items
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)API_AVAILABLE(macos(10.6), ios(2.0)); 復(fù)制代碼查詢關(guān)鍵代碼:
NSDictionary *matchSecItems = @{(id)kSecClass: (id)kSecClassGenericPassword,(id)kSecAttrService: service,(id)kSecAttrAccount: account,(id)kSecMatchLimit: (id)kSecMatchLimitOne,(id)kSecReturnData: @(YES)};CFTypeRef dataRef = nil;OSStatus errorCode = SecItemCopyMatching((CFDictionaryRef)matchSecItems, (CFTypeRef *)&dataRef); 復(fù)制代碼SecItemUpdate:修改匹配搜索查詢的一個(gè)item或多個(gè)items
OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)API_AVAILABLE(macos(10.6), ios(2.0)); 復(fù)制代碼注意:更新代碼這部分,筆者開始的時(shí)候遇到一些問題,還要多謝組內(nèi)成員,尤其是昆哥的指教。
SecItemUpdate接收了2個(gè)參數(shù),query和attributesToUpdate。
第一個(gè)參數(shù)query用于查詢到相應(yīng)的item, 第二個(gè)參數(shù)attributesToUpdate用于傳入要更新的信息。
筆者曾錯(cuò)誤地給第二個(gè)參數(shù)attributesToUpdate傳入過(id)kSecClass: (id)kSecClassGenericPassword要更改的內(nèi)容。
結(jié)果報(bào)錯(cuò)為:
errSecNoSuchAttr = -25303, /* The specified attribute does not exist. */
更新關(guān)鍵代碼:
NSDictionary *queryItems = @{(id)kSecClass: (id)kSecClassGenericPassword,(id)kSecAttrService: service,(id)kSecAttrAccount: account};NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];NSDictionary *updatedItems = @{(id)kSecValueData: passwordData,};OSStatus updateStatus = SecItemUpdate((CFDictionaryRef)queryItems, (CFDictionaryRef)updatedItems); 復(fù)制代碼SecItemDelete:刪除匹配搜索查詢的一個(gè)item或多個(gè)items
OSStatus SecItemDelete(CFDictionaryRef query)API_AVAILABLE(macos(10.6), ios(2.0)); 復(fù)制代碼刪除關(guān)鍵代碼:
NSDictionary *deleteSecItems = @{(id)kSecClass: (id)kSecClassGenericPassword,(id)kSecAttrService: service,(id)kSecAttrAccount: account};OSStatus errorCode = SecItemDelete((CFDictionaryRef)deleteSecItems); 復(fù)制代碼顯然keychain的增刪改查相關(guān)的API都需要設(shè)置相應(yīng)的屬性字典(分別代指上述的saveSecItems 、matchSecItems 、queryItems 、updatedItems 、deleteSecItems)
- 屬性字典的key、value常用的有:(這部分內(nèi)容讀者也可直接看文檔)
- (id)kSecClass: (id)kSecClassGenericPassword kSecClass表示item的class (id)kSecClass的值表明一個(gè)通用的密碼item筆者一般都傳入kSecClassGenericPassword
- (id)kSecAttrService: service kSecAttrService的value用于表明item的service
- (id)kSecAttrAccount: account (id)kSecAttrAccoun的值表明item的帳戶名
- (id)kSecValueData: passwordData (id)kSecValueData表示item的數(shù)據(jù)
- (id)kSecMatchLimit: (id)kSecMatchLimitOne, (id)kSecMatchLimit 有2個(gè)值(id)kSecMatchLimitOne、和(id)kSecMatchLimitAll kSecMatchLimitOne:表示只匹配第一個(gè)符合條件的item kSecMatchLimitAll:表示匹配不限數(shù)量的items
- (id)kSecReturnData: @(YES) (id)kSecReturnData的值是一個(gè)Boolean類型的值用于確定是否返回item data
- kSecClass的值表示item的class kSecClass的值表明一個(gè)通用的密碼item筆者一般都傳入的kSecClassGenericPassword
- kSecClass的值表示item的class kSecClass的值表明一個(gè)通用的密碼item筆者一般都傳入的kSecClassGenericPassword
Demo(QiKeychain)相關(guān)代碼
在Demo(QiKeychain)中,筆者對(duì)keychain相關(guān)使用的API進(jìn)行了封裝。獲取Demo(QiKeychain)GitHub地址:QiKeychain。
注意:筆者后來封裝的代碼,修改了保存操作的邏輯。
修改內(nèi)容為:在保存用戶名密碼的時(shí)候
-> 先在keychain中查詢用戶名是否存在
-> 若存在,就進(jìn)行更新操作;
-> 若不存在就進(jìn)行保存操作。
相應(yīng)示意圖(使用鑰匙串存儲(chǔ)網(wǎng)絡(luò)密碼)如下:
參考學(xué)習(xí)地址
- Keychain Services
- SAMKeychain
小編微信:可加并拉入《QiShare技術(shù)交流群》。
關(guān)注我們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公眾號(hào))
推薦文章:
iOS 自定義拖拽式控件:QiDragView
iOS 自定義卡片式控件:QiCardView
iOS Wireshark抓包
iOS Charles抓包
初探TCP
IP、UDP初探
奇舞周刊
總結(jié)
以上是生活随笔為你收集整理的iOS 钥匙串的基本使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做梦梦到戒指坏了是什么意思
- 下一篇: 【译】 WebSocket 协议第八章—