以编程方式(从我的应用程序中)获取存储在钥匙串中的所有项目的最简单方法是什么?枚举我的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