以編程方式(從我的應用程序中)獲取存儲在鑰匙串中的所有項目的最簡單方法是什麼?枚舉我的iOS應用程序中的所有鑰匙串項目
它可能與SecItemCopyMatching()有關,但該函數的文檔不是很清楚(我沒有找到一個體面的樣本在網上)。
以編程方式(從我的應用程序中)獲取存儲在鑰匙串中的所有項目的最簡單方法是什麼?枚舉我的iOS應用程序中的所有鑰匙串項目
它可能與SecItemCopyMatching()有關,但該函數的文檔不是很清楚(我沒有找到一個體面的樣本在網上)。
SecItemCopyMatching
是正確的要求。首先,我們建立我們的查詢字典,使得項目屬性在字典回來了,這個返回的所有項目:
NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:
(__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnAttributes,
(__bridge id)kSecMatchLimitAll, (__bridge id)kSecMatchLimit,
nil];
由於SecItemCopyMatching
至少需要類返回SecItem
S的,我們創造了所有的數組類...
NSArray *secItemClasses = [NSArray arrayWithObjects:
(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecClassInternetPassword,
(__bridge id)kSecClassCertificate,
(__bridge id)kSecClassKey,
(__bridge id)kSecClassIdentity,
nil];
...併爲每個類,設置類在我們的查詢,請致電SecItemCopyMatching
,並記錄結果。
for (id secItemClass in secItemClasses) {
[query setObject:secItemClass forKey:(__bridge id)kSecClass];
CFTypeRef result = NULL;
SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
NSLog(@"%@", (__bridge id)result);
if (result != NULL) CFRelease(result);
}
在生產代碼中,你應該檢查由SecItemCopyMatching
返回OSStatus
或者是errSecItemNotFound
或errSecSuccess
(找不到項目)(至少一個項目被發現)。
斯威夫特3+版本,還返回鍵(kSecAttrAccount):
open func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] {
var query: [String: Any] = [
kSecClass : secClass,
kSecReturnData : kCFBooleanTrue,
kSecReturnAttributes : kCFBooleanTrue,
kSecReturnRef : kCFBooleanTrue,
kSecMatchLimit : kSecMatchLimitAll
]
var result: AnyObject?
let lastResultCode = withUnsafeMutablePointer(to: &result) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
var values = [String:String]()
if lastResultCode == noErr {
let array = result as? Array<Dictionary<String, Any>>
for item in array! {
if let key = item[kSecAttrAccount] as? String,
let value = item[kSecValueData] as? Data {
values[key] = String(data: value, encoding:.utf8)
}
}
}
return values
}
在Xcode 9.2上使用Swift 3時,在'let key:String = item [kSecAttrAccount] as!字符串'無法將類型'__NSCFData'(0x109b30348)的值轉換爲'NSString'(0x1069030d0).'。我不知道爲什麼。 –
更改設置鍵和值的行使得崩潰不會發生,儘管它消除了我不確定如何抽出的幾個對象:'if let key = item [kSecAttrAccount] as?字符串,讓value = item [kSecValueData]爲?數據{' –
斯威夫特3版和Xcode 9.1
func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] {
var query: [String: Any] = [
kSecClass as String : secClass,
kSecReturnData as String : kCFBooleanTrue,
kSecReturnAttributes as String : kCFBooleanTrue,
kSecReturnRef as String : kCFBooleanTrue,
kSecMatchLimit as String : kSecMatchLimitAll
]
var result: AnyObject?
let lastResultCode = withUnsafeMutablePointer(to: &result) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
var values = [String:String]()
if lastResultCode == noErr {
let array = result as? Array<Dictionary<String, Any>>
for item in array! {
if let key = item[kSecAttrAccount as String] as? String,
let value = item[kSecValueData as String] as? Data {
values[key] = String(data: value, encoding:.utf8)
}
}
}
return values
}
可以這樣調用:
debugPrint(getAllKeyChainItemsOfClass(kSecClassGenericPassword as String))
謝謝!還沒有測試過,但看起來是正確的答案。 – noamtm
是。我測試了它:) –
我在iPhone和模擬器打印出來都是空的。還有什麼我應該做的嗎? – karim