钥匙串访问控制(带密码后备的 TouchID)
Keychain 允许使用特殊的 SecAccessControl 属性保存项目,这样只有在用户使用 Touch ID 进行身份验证后才能从 Keychain 获取项目(如果允许这样的回退,则允许使用密码)。仅通知应用程序验证是否成功,整个 UI 由 iOS 管理。
首先,应创建 SecAccessControl 对象:
迅速
let error: Unmanaged<CFError>?
guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, .userPresence, &error) else {
fatalError("Something went wrong")
}
接下来,使用 kSecAttrAccessControl 键将其添加到字典中(与其他示例中使用的 kSecAttrAccessible 键互斥):
迅速
var dictionary = [String : Any]()
dictionary[kSecClass as String] = kSecClassGenericPassword
dictionary[kSecAttrLabel as String] = "com.me.myapp.myaccountpassword" as CFString
dictionary[kSecAttrAccount as String] = "My Name" as CFString
dictionary[kSecValueData as String] = "new_password!!".data(using: .utf8) as! CFData
dictionary[kSecAttrAccessControl as String] = accessControl
并像以前一样保存它:
迅速
let lastResultCode = SecItemAdd(query as CFDictionary, nil)
要访问存储的数据,只需查询 Keychain 以获取密钥。Keychain Services 将向用户显示身份验证对话框并返回数据或 nil,具体取决于是否提供了合适的指纹或匹配的密码。
(可选)可以指定提示字符串:
迅速
var query = [String: Any]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecReturnData as String] = kCFBooleanTrue
query[kSecAttrAccount as String] = "My Name" as CFString
query[kSecAttrLabel as String] = "com.me.myapp.myaccountpassword" as CFString
query[kSecUseOperationPrompt as String] = "Please put your fingers on that button" as CFString
var queryResult: AnyObject?
let status = withUnsafeMutablePointer(to: &queryResult) {
SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
}
如果用户拒绝,取消或未通过授权,请注意 status
将成为 err
。
迅速
if status == noErr {
let password = String(data: queryResult as! Data, encoding: .utf8)!
print("Password: \(password)")
} else {
print("Authorization not passed")
}