2012-06-10 35 views
29

以編程方式(從我的應用程序中)獲取存儲在鑰匙串中的所有項目的最簡單方法是什麼?枚舉我的iOS應用程序中的所有鑰匙串項目

它可能與SecItemCopyMatching()有關,但該函數的文檔不是很清楚(我沒有找到一個體面的樣本在網上)。

回答

46

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或者是errSecItemNotFounderrSecSuccess(找不到項目)(至少一個項目被發現)。

+0

謝謝!還沒有測試過,但看起來是正確的答案。 – noamtm

+2

是。我測試了它:) –

+0

我在iPhone和模擬器打印出來都是空的。還有什麼我應該做的嗎? – karim

3

斯威夫特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 
    } 
+0

在Xcode 9.2上使用Swift 3時,在'let key:String = item [kSecAttrAccount] as!字符串'無法將類型'__NSCFData'(0x109b30348)的值轉換爲'NSString'(0x1069030d0).'。我不知道爲什麼。 –

+1

更改設置鍵和值的行使得崩潰不會發生,儘管它消除了我不確定如何抽出的幾個對象:'if let key = item [kSecAttrAccount] as?字符串,讓value = item [kSecValueData]爲?數據{' –

0

斯威夫特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)) 
相關問題