如何通過鑰匙串和生物識別技術來保護iOS的用戶數據
使用登錄屏幕保護應用程序是保護用戶數據的絕佳方法,你可以使用內置於iOS的鑰匙串來確保數據的安全。 另外,蘋果還通過生物識別技術,比如人臉ID和觸摸ID提供了另一層保護。
從iPhone 5S開始,生物識別數據就被存儲在採用了64位架構的蘋果A7處理器和最新晶元的安全區域。這就意味著你可以輕鬆地將處理登錄信息的任務交給鑰匙串以及人臉ID或觸摸ID。
在本文中,你將從靜態身份驗證開始。一步一步地使用鑰匙串來存儲和驗證登錄信息。最後,你將在你的應用中學會如何使用觸摸ID或人臉ID。
請注意:人臉ID需要你在物理設備上進行測試。觸摸ID現在可以在模擬器的Xcode 9中模擬。鑰匙串也可以在模擬器中使用。在本文中,在大多數情況下,我都是針對觸摸ID進行介紹的,不過這個過程也適用於人臉ID,因為其底層的 LocalAuthentication框架都是相同的。
前期準備工作
首先,請點此下載一個操作模板。
這是一個基本的筆記應用程序,使用核心數據來存儲用戶的操作數據,操作板上有一個登錄視圖,用戶可以輸入用戶名和密碼,而應用程序視圖的其餘部分已經相互連接並可以使用。
構建並運行以查看你的應用在當前狀態下的樣子:
請注意:你可以忽略關於注釋類型缺失的任何編譯器錯誤。它將由Core Data自動生成。
此時,點擊「登錄」按鈕將簡單地關閉視圖並顯示注釋列表,你也可以從此屏幕創建新記錄。點擊註銷就可以返回到登錄視圖。如果應用程序在後台使用,它會立即返回到登錄視圖,這可以保護數據不被查看。
在你執行其它操作之前,你應該改變包標識符(bundle identifier)並指定一個適當的「組」。
在項目導航器中選擇TouchMeIn,然後選擇TouchMeIn目標。在General選項卡中,將Bundle Identifier更改為使用你自己的域名,以反向域標記 (reverse-domain-notation),例如com.raywenderich.TouchMeIn。
然後,從「組」菜單中,選擇與你的開發者帳戶關聯的組,如下所示:
完成所有的前期準備工作後,就可以編寫登錄代碼了。
編寫登錄代碼
此時你需要將用戶提供的憑證添加進來,以對抗硬編碼的值。
打開LoginViewController.swift並在managedObjectContext下方添加以下常量:
let usernameKey = "Batman"
let passwordKey = "Hello Bruce!"
這些只是硬編碼的用戶名和密碼,你將檢查用戶提供的憑據。
接下來,在loginAction(_:)下面添加以下方法:
func checkLogin(username: String, password: String) -> Bool {
return username == usernameKey && password == passwordKey
}
此時,你可以根據以前定義的常量檢查用戶提供的憑據。
接下來,將loginAction(_:)內容替換為以下內容:
if checkLogin(username: usernameTextField.text!, password: passwordTextField.text!) {
performSegue(withIdentifier: "dismissLogin", sender: self)
}
此時, 只有在憑據正確的情況下,你調用checkLogin(username:password:),才會關閉登錄視圖。
輸入用戶名Batman和密碼Hello Bruce!,然後點擊登錄按鈕,登錄屏幕應該像預期的那樣消失。
雖然這種簡單的身份驗證方法似乎可行,但它並不是非常安全,因為存儲為字元串的憑據很容易被黑客利用合適的工具進行攻擊。所以,密碼不應直接存儲在應用程序中。為此,你需要使用鑰匙串來存儲密碼。
請注意:大多數應用程序的密碼只是簡單的字元串,以bullet的形式隱藏。在應用程序中處理密碼的最佳方式是在捕獲後立即對其進行SALT或SHA-2方式進行加密。只有用戶才知道真實的字元串。
你可以查看Chris Lowe的iOS 5的基本安全性 - 第1部分來了解鑰匙串如何工作。
封裝過程
接下來就是在應用程序中添加一個鑰匙串封裝器。
在一開始下載模板的時候,你會下載了一個有用的資源文件夾。找到並打開Finder中的資源文件夾。你會看到KeychainPasswordItem.swift文件,這個類來自蘋果的樣本代碼GenericKeychain。
將KeychainPasswordItem.swift拖進來,如下所示:
出現提示時,確保Copy items if needed和TouchMeIn選項都被選中:
構建並運行以確保沒有錯誤,如果一切順利,現在你就可以利用你的應用程序中的鑰匙串了。
鑰匙串的使用
要使用鑰匙串,你首先要在其中存儲用戶名和密碼。接下來,你將檢查用戶提供的憑據,以查看它們是否與鑰匙串中存儲的用戶名和密碼匹配。
你需要跟蹤用戶創建的憑據,以便你可以將「登錄」按鈕上的文本從「創建」更改為「登錄」。你還會將用戶名存儲在用戶默認值中,這樣你就可以在每次執行此檢查時自動執行該過程。
鑰匙串需要一些配置才能正確存儲你的應用程序的信息,你將以serviceName和可選的accessGroup的形式提供該配置。最終,你會使用一個結構來存儲這些值。
打開LoginViewController.swift。在導入語句下方添加以下內容:
// Keychain Configuration
struct KeychainConfiguration {
static let serviceName = "TouchMeIn"
static let accessGroup: String? = nil
}
接下來,添加下面的managedObjectContext:
var passwordItems: [KeychainPasswordItem] = []
let createLoginButtonTag = 0
let loginButtonTag = 1
@IBOutlet weak var loginButton: UIButton!
passwordItems是你將傳入鑰匙串的KeychainPasswordItem類型的空數組,這樣你將使用兩個常量來確定登錄按鈕是否被用來創建一些憑據,以便你使用loginButton 輸出口來根據其創建狀態來更新登錄按鈕的標題。
接下來,會出現兩種情況:如果點擊按鈕時,如果用戶還沒有創建憑據,按鈕文本將顯示「創建」;否則按鈕將顯示「登錄」。
首先,如果登錄失敗,你需要選擇一種方法來通知用戶。什麼方法呢?就是在checkLogin(username:password:)後添加以下內容:
private func showLoginFailedAlert() {
let alertView = UIAlertController(title: "Login Problem",
message: "Wrong username or password.",
preferredStyle:. alert)
let okAction = UIAlertAction(title: "Foiled Again!", style: .default)
alertView.addAction(okAction)
present(alertView, animated: true)
}
現在,將loginAction(sender:)替換為以下內容:
@IBAction func loginAction(sender: UIButton) {
// 1
// Check that text has been entered into both the username and password fields.
guard let newAccountName = usernameTextField.text,
let newPassword = passwordTextField.text,
!newAccountName.isEmpty,
!newPassword.isEmpty else {
showLoginFailedAlert()
return
}
// 2
usernameTextField.resignFirstResponder()
passwordTextField.resignFirstResponder()
// 3
if sender.tag == createLoginButtonTag {
// 4
let hasLoginKey = UserDefaults.standard.bool(forKey: "hasLoginKey")
if !hasLoginKey && usernameTextField.hasText {
UserDefaults.standard.setValue(usernameTextField.text, forKey: "username")
}
// 5
do {
// This is a new account, create a new keychain item with the account name.
let passwordItem = KeychainPasswordItem(service: KeychainConfiguration.serviceName,
account: newAccountName,
accessGroup: KeychainConfiguration.accessGroup)
// Save the password for the new item.
try passwordItem.savePassword(newPassword)
} catch {
fatalError("Error updating keychain - (error)")
}
// 6
UserDefaults.standard.set(true, forKey: "hasLoginKey")
loginButton.tag = loginButtonTag
performSegue(withIdentifier: "dismissLogin", sender: self)
} else if sender.tag == loginButtonTag {
// 7
if checkLogin(username: newAccountName, password: newPassword) {
performSegue(withIdentifier: "dismissLogin", sender: self)
} else {
// 8
showLoginFailedAlert()
}
}
}
以下是代碼中發生的進程:
1.如果用戶名或密碼為空,則會向用戶顯示一個警告並返回;
2. 如果鍵盤是可見的,會將它刪除;
3.如果登錄按鈕的標籤是createLoginButtonTag,則會繼續創建一個新的登錄;
4.接下來,你將讀取來自UserDefaults的hasLoginKey,用於指示是否已將密碼保存到鑰匙串中。如果hasLoginKey為false並且用戶名欄位包含了文本,那麼你就將該文本作為用戶名保存到UserDefaults中。
5.使用serviceName,newAccountName(username)和accessGroup創建KeychainPasswordItem。使用Swift的錯誤處理,你可以嘗試保存密碼。如果保存密碼失敗,那麼就是catch出現了問題。
6.然後,你將UserDefaults中的hasLoginKey設置為true,以指示密碼已保存到鑰匙串。你將登錄按鈕的標籤設置為loginButtonTag以更改按鈕的文本信息,以便在用戶下次運行應用程序時提示用戶登錄,而不是提示用戶創建登錄。最後,關閉loginView。
7.如果用戶正在登錄(如loginButtonTag所示),則調用checkLogin來驗證用戶提供的憑證,如果他們匹配,那麼你就可以關閉登錄視圖了。
8.如果登錄認證失敗,則會向用戶顯示一個警告消息。
func checkLogin(username: String, password: String) -> Bool {
guard username == UserDefaults.standard.value(forKey: "username") as? String else {
return false
}
do {
let passwordItem = KeychainPasswordItem(service: KeychainConfiguration.serviceName,
account: username,
accessGroup: KeychainConfiguration.accessGroup)
let keychainPassword = try passwordItem.readPassword()
return password == keychainPassword
} catch {
fatalError("Error reading password from keychain - (error)")
}
}
請注意:你也許會覺得奇怪為什麼不把用戶名密碼和UserDefaults一起存儲呢?因為這是一個很糟糕的想法,因為存儲在UserDefaults中的值是使用plist文件保存的。它本質上是一個駐留在應用程序庫文件夾中的XML文件,因此任何人都可以讀取設備的物理訪問。另一方面,鑰匙串使用三重數字加密標準(3DES)來加密其數據。即使有人獲得這些數據,他們也將無法讀取。
接下來,用以下更新的實現替換checkLogin(username:password:):
let usernameKey = "Batman"
let passwordKey = "Hello Bruce!"
此時,你要檢查輸入的用戶名是否與UserDefaults中存儲的用戶名相匹配,並且密碼與鑰匙串中存儲的密碼相匹配。
接下來,刪除以下幾行:
// 1
let hasLogin = UserDefaults.standard.bool(forKey: "hasLoginKey")
// 2
if hasLogin {
loginButton.setTitle("Login", for: .normal)
loginButton.tag = loginButtonTag
createInfoLabel.isHidden = true
} else {
loginButton.setTitle("Create", for: .normal)
loginButton.tag = createLoginButtonTag
createInfoLabel.isHidden = false
}
// 3
if let storedUsername = UserDefaults.standard.value(forKey: "username") as? String {
usernameTextField.text = storedUsername
}
現在可以根據hasLoginKey的狀態,適當地設置按鈕標題和標籤了。
將下面的代碼添加到viewDidLoad()中,然後調用super::
依次對每個編號進行注釋:
1.首先你要檢查hasLoginKey,看看你是否已經為該用戶存儲了一個登錄名;
2.如果是這樣,將按鈕的標題更改為Login,將其標籤更新為loginButtonTag,並隱藏createInfoLabel,其中包含信息文本「以創建用戶名和密碼開始」。如果你沒有該用戶的存儲登錄信息,則將按鈕標籤設置為「創建」並將createInfoLabel顯示給用戶。
3.最後,你需要將用戶名欄位設置為UserDefaults中保存的內容,以便為用戶提供更方便的日誌記錄。
最後,需要將輸出口連接到登錄按鈕。打開Main.storyboard並選擇登錄 Login View Controller Scene。按住Ctrl鍵,從「登錄視圖控制器」拖動到「登錄」按鈕,如下所示:
在彈出窗口中,選擇loginButton:
運行時,輸入你自己選擇的用戶名和密碼,然後點擊創建。
請注意,如果你忘記連接loginButton 輸出口,那麼你可能會看到錯誤的Fatal error: unexpectedly found nil while unwrapping an Optional value,如果是這樣,請按照上述相關步驟連接輸出口。
現在,點擊註銷並嘗試使用相同的用戶名和密碼登錄 ,此時你應該會看到出現的注釋列表。
點擊註銷並嘗試重新登錄,不過這次使用的是不同的密碼,然後點擊登錄。此時,你應該會看到以下警告:
現在你已經可以使用鑰匙串添加身份驗證了。接下來,就可以開始創建觸摸ID了。
觸摸ID
請注意:人臉ID要求你在物理設備(如iPhone X)上進行測試,觸摸ID現在可以在模擬器中的Xcode 9中模擬。你可以在任何使用A7晶元或更新的設備和人臉ID / 觸摸ID硬體的設備上測試生物識別ID。
在本節中,除了使用鑰匙串之外,你還需要將生物識別ID添加到你的項目中。雖然鑰匙串不需要人臉ID / 觸摸ID,但對於生物識別ID失敗的實例,或者對於沒有Touch ID兼容設備的用戶來說,實現備份身份驗證就是不可能的事情了。
打開Assets.xcassets,接下來,從你在Finder中先前下載的項目中打開Resources文件夾。找到FaceIcon和Touch-icon-lg.png圖像,並將它們拖到Images.xcassets中,以便Xcode知道它們是相同的圖像,唯一的差別就是解析度:
打開Main.storyboard並把對象庫中的按鈕拖動到堆棧視圖中的「創建信息標籤」下方的Login View Controller Scene中。你可以打開Document Outline,打開開合三角標識,並確保Button在堆棧視圖內。如下所示:
如果你需要查看堆棧視圖,請參閱UIStackView教程:介紹堆棧視圖。
在「屬性」檢查器中,按如下所示調整按鈕的屬性:
1.將類型設置為自定義。
2.將標題留空。
3.將圖像設置為Touch-icon-lg。
完成後,按鈕的屬性應如下所示:
此時,你要確保新的按鈕被選中,然後單擊面板布底部布局欄中的「添加新約束」按鈕,並將約束條件設置如下:
寬度應該是66,身高應該是67,點擊Add 2約束,操作視圖現在應該如下所示。
現在,你仍然在Main.storyboard中,打開輔助編輯器並確保顯示LoginViewController.swift。
接下來,就像在其它輸出口一樣,從你剛添加到LoginViewController.swift的按鈕中選擇控制標記(Control-drag)。
在彈出框中輸入touchIDButton,然後單擊連接:
這樣,你會創建一個輸出口,用於隱藏沒有生物識別ID的設備上的按鈕。
接下來,你需要為該按鈕添加一個操作。
把來自同一個按鈕的控制標記拖動到LoginViewController.swift,也就是 checkLogin(username:password:)的上面。
在彈出窗口中,將Connection更改為Action,將Name設置為touchIDLoginAction,現在將Arguments設置為none。然後點擊連接。
運行以檢查是否有任何錯誤,由於目前你尚未添加對生物識別ID的支持,因此你仍然可以創建模擬器。
添加本地認證
實現生物識別ID就像導入本地認證框架和調用一些簡單而強大的方法一樣簡單。
以下是本地認證的解釋:
「本地身份驗證框架提供了用於請求用戶使用指定的安全策略進行身份驗證的工具」,而本文所指定的安全策略就是用戶的生物識別技術 。
iOS 11的新功能支持人臉ID,LocalAuthentication添加了一些新的功能:所需的FaceIDUsageDescription和LABiometryType是用來確定設備是否支持人臉ID或觸摸ID。
在Xcode的項目導航器中選擇項目並單擊Info選項卡,將滑鼠懸停在其中一個鍵的右側,然後單擊+。開始輸入「隱私」,然後在出現的彈出列表中選擇「隱私 - 臉部ID使用說明」。
請注意:你也可以輸入「NSFaceIDUsageDescription」。
這是字元串,在value欄位中,你可以使用Face ID來解鎖這些注釋。
在項目導航器中,右鍵單擊TouchMeIn組文件夾並選擇New File,直到找到iOS Swift文件,然後點擊下一步。將TouchMeIn目標文件保存為TouchIDAuthentication.swift。點擊創建。
打開TouchIDAuthentication.swift並在import Foundation添加以下導入:
import LocalAuthentication
接下來,添加以下內容來創建一個新的類:
class BiometricIDAuth {
}
現在你需要引用LAContext類,在這個類中,在花括弧之間添加以下代碼。
let context = LAContext()
用上下文引用認證上下文,這是本地認證的主要特點。你需要一個函數來查看用戶設備或模擬器中是否有生物識別ID。
如果BiometricIDAuth內部支持生物特徵ID,則添加以下方法以返回Bool:
func canEvaluatePolicy() -> Bool {
return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
}
打開LoginViewController.swift並添加以下屬性以創建對BiometricIDAuth的引用:
let touchMe = BiometricIDAuth()
在viewDidLoad()底部添加如下內容:
touchIDButton.isHidden = !touchMe.canEvaluatePolicy()
在本文,你可以使用canEvaluatePolicy(_:)來檢查設備是否可以實現生物認證。如果是,則顯示觸摸ID按鈕,如果沒有,請將其隱藏。
在模擬器上構建並運行,此時你會看到觸摸ID標誌已隱藏。現在建立和運行你的人臉ID或觸摸ID的設備,此時,你會看到觸摸ID按鈕被顯示出來。在模擬器中,你可以從硬體菜單中依次選擇觸摸ID>註冊並測試按鈕。
面部ID或觸摸ID
如果你使用的是iPhone X或更高版本的人臉ID設備,那就要注意了。因為此時,觸摸ID圖標 已經被處理過了,不存在了。不過,你可以使用biometryType枚舉類型來解決這個問題。
打開TouchIDAuthentication.swift並在類的上方添加BiometricType枚舉。
enum BiometricType {
case none
case touchID
case faceID}
接下來,添加以下函數以使用canEvaluatePolicy返回來選擇支持的生物特徵類型。
func biometricType() -> BiometricType {
let _ = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
switch context.biometryType {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
}
}
打開LoginViewController並將以下內容添加到viewDidLoad()的底部,以修復按鈕的圖標:
switch touchMe.biometricType() {
case .faceID:
touchIDButton.setImage(UIImage(named: "FaceIcon"), for: .normal)
default:
touchIDButton.setImage(UIImage(named: "Touch-icon-lg"), for: .normal)
}
在觸摸ID註冊的模擬器上構建並運行,查看觸摸ID圖標,此時你會看到臉部ID圖標顯示在iPhone X上。
讓觸摸ID正常工作
打開TouchIDAuthentication.swift並在上下文中添加以下變數:
var loginReason = "Logging in with Touch ID"
以上解釋了應用程序請求驗證的原因,該原因將在顯示的對話框中。
接下來,將下面的方法添加到BiometricIDAuth的底部以對用戶進行身份驗證。
func authenticateUser(completion: @escaping () -> Void) { // 1
// 2
guard canEvaluatePolicy() else {
return
}
// 3
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
localizedReason: loginReason) { (success, evaluateError) in
// 4
if success {
DispatchQueue.main.async {
// User authenticated successfully, take appropriate action
completion()
}
} else {
// TODO: deal with LAError cases
}
}
}
以下就是上述代碼中發生的進程:
1.authenticateUser(completion :)以閉包的形式提供了一個完成處理程序;
2.你正在使用canEvaluatePolicy()來檢查該設備是否有能力進行生物認證。
3.如果設備支持生物識別ID,則使用evaluatePolicy(_:localizedReason:reply:)開始策略評估,即提示用戶進行生物識別身份驗證。 評估完成後,evaluatePolicy(_:localizedReason:reply:)會進行立即回復。
4.在回復代碼塊中,首先處理成功案例。默認情況下,策略評估會發生在一個專用線程上,所以代碼會跳轉到主線程,以便它可以更新UI。如果驗證成功,你將調用拒絕登錄視圖的segue。
打開LoginViewController.swift,找到touchIDLoginAction(_:)並將其替換為以下內容:
@IBAction func touchIDLoginAction() {
touchMe.authenticateUser() { [weak self] in
self?.performSegue(withIdentifier: "dismissLogin", sender: self)
}
}
如果用戶通過身份驗證,則可以關閉「登錄」視圖。
處理錯誤
如果你沒有在你的設備上設置生物識別ID,那該怎麼辦?本地身份驗證的一個重要部分是錯誤響應,所以框架會包含一個LAError類型,不過也有可能是從第二次使用canEvaluatePolicy獲得一個錯誤。
此時,你會收到一個警告,告訴你出了什麼問題。你需要將TouchIDAuth類的消息傳遞給LoginViewController。幸運的是,你可以使用完成處理程序來傳遞可選消息。
打開TouchIDAuthentication.swift並更新authenticateUser方法。
更改簽名以包含一個可選的消息,即遇到錯誤時的提示消息。
func authenticateUser(completion: @escaping (String?) -> Void) {
接下來,查找// TODO:並將其替換為以下內容。
// 1
let message: String
// 2
switch evaluateError {
// 3
case LAError.authenticationFailed?:
message = "There was a problem verifying your identity."
case LAError.userCancel?:
message = "You pressed cancel."
case LAError.userFallback?:
message = "You pressed password."
case LAError.biometryNotAvailable?:
message = "Face ID/Touch ID is not available."
case LAError.biometryNotEnrolled?:
message = "Face ID/Touch ID is not set up."
case LAError.biometryLockout?:
message = "Face ID/Touch ID is locked."
default:
message = "Face ID/Touch ID may not be configured"
}
// 4
completion(message)
過程如下:
1.用一個字元串來保存消息;
2.查看「失敗」案例,你可以使用switch語句為每個錯誤情況設置相應的錯誤消息,然後向用戶顯示警告視圖。
3.如果身份驗證失敗,則顯示警告。實際上,你應該真正評估並解決返回的特定錯誤代碼:
3.1 LAError.biometryNotAvailable:該設備不兼容人臉ID 或觸摸ID;
3.2 LAError.passcodeNotSet:根據觸摸ID的要求,沒有啟用密碼;
3.3 LAError.biometryNotEnrolled:沒有存儲的臉部或指紋。
3.4 LAError.biometryLockout:失敗的嘗試太多了。
4.在completion 閉包中傳遞消息。
iOS會響應與LAError.passcodeNotSet和LAError.biometryNotEnrolled相關的警告。
還有一個錯誤需要處理,就是在guard語句的else塊中添加以下內容,只需return即可。
completion("Touch ID not available")
最後要更新的是成功案例,完成後應該包含nil,這表明你沒有得到任何錯誤,在第一個成功塊中添加了nil。
completion(nil)
完成這些更改後,完成的方法應該如下所示:
func authenticateUser(completion: @escaping (String?) -> Void) {
guard canEvaluatePolicy() else {
completion("Touch ID not available")
return
}
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
localizedReason: loginReason) { (success, evaluateError) in
if success {
DispatchQueue.main.async {
completion(nil)
}
} else {
let message: String
switch evaluateError {
case LAError.authenticationFailed?:
message = "There was a problem verifying your identity."
case LAError.userCancel?:
message = "You pressed cancel."
case LAError.userFallback?:
message = "You pressed password."
case LAError.biometryNotAvailable?:
message = "Face ID/Touch ID is not available."
case LAError.biometryNotEnrolled?:
message = "Face ID/Touch ID is not set up."
case LAError.biometryLockout?:
message = "Face ID/Touch ID is locked."
default:
message = "Face ID/Touch ID may not be configured"
}
completion(message)
}
}
}
請注意:編譯錯誤處理時,你會看到三條警告,都是關於使用的常量。這是由於蘋果增加了對人臉ID的支持,以及Swift導入Objective-C頭文件的方式。雖然有一些潛在的解決方法,但是它們遠不如「Swift-like」。由於蘋果已經意識到這個問題,並計劃在未來修復這個問題,所以我想在此簡單介紹一下。
打開LoginViewController.swift並更新touchIDLoginAction(_:),如下所示:
@IBAction func touchIDLoginAction() {
// 1
touchMe.authenticateUser() { [weak self] message in
// 2
if let message = message {
// if the completion is not nil show an alert
let alertView = UIAlertController(title: "Error",
message: message,
preferredStyle: .alert)
let okAction = UIAlertAction(title: "Darn!", style: .default)
alertView.addAction(okAction)
self?.present(alertView, animated: true)
} else {
// 3
self?.performSegue(withIdentifier: "dismissLogin", sender: self)
}
}
}
進程如下:
1.你已經更新了閉包以接受可選消息,如果生物特徵ID有效,則不存在消息;
2. 如果允許打開消息並顯示警告,你可以使用它;
3.如果沒有消息,你可以關閉登錄視圖。
在物理設備上構建並運行,然後使用觸摸ID測試登錄。
由於LAContext處理了大部分繁重的工作,所以實現生物識別ID相對來說比較簡單。作為回報,你可以在同一個應用程序中使用鑰匙串和生物識別身份驗證,來處理用戶沒有使用觸摸ID的設備的事件。
請注意:如果你想要測試觸摸ID中的錯誤,你可以嘗試故意錯誤登錄。這樣做五次,你將被禁用使用觸摸ID,並要求密碼身份驗證。這可以防止其他人控制你設備上的其他應用程序。你可以通過設置 >觸摸ID和密碼重新啟用它。
人臉ID的使用
關於iPhone X的最酷的事情之一是使用臉部識別而不用觸摸屏幕。你可以通過添加了一個可用於觸發人臉ID的按鈕,但也可以自動觸發人臉ID。
打開LoginViewController.swift並在viewDidLoad()下面添加如下代碼:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let touchBool = touchMe.canEvaluatePolicy()
if touchBool {
touchIDLoginAction()
}
}
這將驗證你的設備是否支持生物識別ID,如果支持,則設備將嘗試驗證用戶。
在裝有iPhone X或人臉ID的設備上構建並運行,以測試運行是否正常。
你可以從這裡下載完整的示例應用程序。
你在本文中創建的LoginViewController可以為任何需要管理用戶憑證的應用程序提供參考。
你還可以添加一個新的視圖控制器,或修改現有的LoginViewController,以允許用戶隨時更改密碼。不過,這對於生物識別ID來說是不必要的,但是,你可以創建一個更新鑰匙串的方法,以提示用戶在修改密碼時輸入當前的密碼。
蘋果還建議在使用人臉ID時隱藏用戶名、密碼欄位以及登錄按鈕。你可以在蘋果的官方iOS安全指南中了解更多有關保護你的iOS應用程序的信息。
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
TAG:嘶吼RoarTalk |