Touch ID是苹果生物指纹授权技术,首先是在iPhone 5s上被看到。Touch ID嵌入home建非常方便使用。一旦你的手指触摸home建,Touch ID传感器将立马读取你的指纹,通过分析,确定你是否可以访问iPhone。安全和私有是Touch ID传感器的最大两个关注点。根据苹果,你的设备不能够存储任意包含你的指纹的图片。通过扫描指纹转换到数学显示并且进行加密存储到安全的芯片当中。
第一次公开是iOS7,我们能够使用Touch ID来解锁我们的iPhone,并且可以授权购物,付款等各种功能。iOS7的时候,苹果并不允许开发者在自己的APP中使用APIs来实现Touch ID的授权操作。随着新版本的发布,苹果拥有了大量的新技术和框架,iOS8使用了新技术,然后公开了Touch ID的API可以进行使用。使用Touch ID可以取代使用密码,要使用Touch ID需要使用新的框架,为Local Authentication.该框架提供了方法进行授权操作,并且提供了许多机会访问APP的敏感信息。
Local Authentication框架的核心是LAContext类,提供了两个方法:
canEvaluatePolicy(_:error:):该方法进行评估给与的授权策略是否能够进行授权,在进行写入的时候,DeviceOwnerAuthenticationWithBiometrics是唯一的策略。如果方法返回的是正数,意味着设备支持Touch ID授权。另一方面,如果返回是负数,该设备可能没有Touch ID传感器或者用户并不能够使用指纹授权特性。
evaluatePolicy(_:localizedReason:reply:):当方法被调用的时候,它将呈现授权提示框,请求指纹扫描。授权是异步执行的,当授权完成,reply block将被调用并且回调授权结果。如果授权失败,将返回LAError对象说明出错的原因。
上面理论部分内容已经足够了,现在开始来玩玩代码:原文地址内容
功能描述:运行程序得到一个授权界面,通过授权进入文本编辑界面,如果之前使用过KeychainWrapper存储过输入的内容,那么本次授权之后,会直接显示上次显示的内容,如果上次没有存储过内容,那么需要新输入内容进行存储,然后再次授权进行验证是否存储成功,效果如下图:
import LocalAuthentication
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var secret: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
title = "Nothing to see here"
//添加相应的键盘通知
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: Notification.Name.UIKeyboardWillHide, object: nil)
notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: Notification.Name.UIKeyboardWillChangeFrame, object: nil)
//当APP不在活跃,即在前台运行,或当设备被锁,或回到home页,或切换到多任务模式,或进入后台都除触发通知,并保存当前输入的数据,下次进行直接授权查看之前保存的数据
notificationCenter.addObserver(self, selector: #selector(saveSecretMessage), name: Notification.Name.UIApplicationWillResignActive, object: nil)
}
//根据键盘的显示和消失调节textview的位置
func adjustForKeyboard(notification: Notification) {
let userInfo = notification.userInfo!
let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)
if notification.name == NSNotification.Name.UIKeyboardWillHide {
secret.contentInset = UIEdgeInsets.zero
} else {
secret.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0)
}
secret.scrollIndicatorInsets = secret.contentInset
let selectedRange = secret.selectedRange
secret.scrollRangeToVisible(selectedRange)
}
//点击授权按钮
@IBAction func authenticateTapped(_ sender: AnyObject) {
let context = LAContext()
var error: NSError?
//询问是否可以进行授权,返回True表示支持. Touch ID是Local Authentication framework的一部分,我们的代码需要做3件事:1)确认设备是否支持生物识别授权 2)如果支持,请求 Touch ID开始确认,并且给与一个字符串,字符串说明我们使用 Touch ID的原因 3)如果我们在进行 Touch ID授权之后,返回成功表示设备持有者能够解锁APP,是否显示错误信息。
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Identify yourself!"
//注意:闭包中使用无主引用防止循环引用
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
[unowned self] (success, authenticationError) in
//这里需要注意:当我们被告知授权是否成功,当前线程不一定是主线程,所以我们要确保回到主线程更新用户界面。
DispatchQueue.main.async {
if success {
//授权成功,显示保存的信息
self.unlockSecretMessage()
} else {
//授权失败,提示出错
let ac = UIAlertController(title: "Authentication failed", message: "Your fingerprint could not be verified; please try again.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
self.present(ac, animated: true)
}
}
}
} else {
var errorMessage:String = ""
if let error = error {
switch error.code {
case LAError.authenticationFailed.rawValue:
errorMessage = "Authentication failed because the fingerprint does not match up with those enrolled."
case LAError.passcodeNotSet.rawValue:
errorMessage = "Passcode not set"
case LAError.systemCancel.rawValue:
errorMessage = "Authentication was canceled by system"
case LAError.userCancel.rawValue:
errorMessage = "Authentication was canceled by the user"
case LAError.touchIDNotEnrolled.rawValue:
errorMessage = "Authentication could not start because Touch ID has no enrolled fingers."
case LAError.touchIDNotAvailable.rawValue:
errorMessage = "Authentication could not start because Touch ID is not available."
case LAError.userFallback.rawValue:
errorMessage = "User tapped the fallback button (Enter Password)."
default:
errorMessage = error.localizedDescription
}
}
let ac = UIAlertController(title: "Touch ID not available", message: errorMessage, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
self.present(ac, animated: true)
}
}
//加载秘密信息显示到textview上
func unlockSecretMessage() {
secret.isHidden = false
title = "Secret stuff!"
//获取存储的信息
if let text = KeychainWrapper.standardKeychainAccess().string(forKey: "SecretMessage") {
secret.text = text
}
}
//保持textview中输入的信息到Keychain
func saveSecretMessage() {
if !secret.isHidden {
//存储textview中的信息
KeychainWrapper.standardKeychainAccess().setString(secret.text, forKey: "SecretMessage")
//去除textview
secret.resignFirstResponder()
//隐藏textview
secret.isHidden = true
title = "Nothing to see here"
}
}
}