鑰匙串訪問控制(帶密碼後備的 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")
}