title | toc |
---|---|
生物识别验证 |
true |
Table of Contents
[TOC]
iOS 现阶段有 3 种本地验证方式, 分别是
- Passcode
- TouchID
- FaceID
macOS 现阶段有 2 种本地验证方式, 分别是
- Password
- TouchID
比如 KeyChain
的调用在获取 API 中有参数可以自动带有生物识别验证方式, 这里不做赘述, 这里我们仅仅讨论自定义的验证机制.
在使用 FaceID
时, 我们要向 App 的 Info.plist
中添加 NSFaceIDUsageDescription
的权限描述.
在 iOS 11
之后 TouchID
的相关参数及方法全部都被替换成 Biometrics
了, 也就说 Biometrics
包含了 TouchID
和 FaceID
, 具体由系统去判断, 因为现在并没出现两者同时出现的迹象, 而且 Apple 貌似并不想让他们同时出现.
我们用到的就是这个库
import LocalAuthentication
这个类是我们主要操作的对象. 下面我们来介绍一下, 我们一般会用到的验证方法
/// Determines if a particular policy can be evaluated.
///
/// @discussion Policies can have certain requirements which, when not satisfied, would always cause
/// the policy evaluation to fail - e.g. a passcode set, a fingerprint
/// enrolled with Touch ID or a face set up with Face ID. This method allows easy checking
/// for such conditions.
///
/// Applications should consume the returned value immediately and avoid relying on it
/// for an extensive period of time. At least, it is guaranteed to stay valid until the
/// application enters background.
///
/// @warning Do not call this method in the reply block of evaluatePolicy:reply: because it could
/// lead to a deadlock.
///
/// @param policy Policy for which the preflight check should be run.
///
/// @param error Optional output parameter which is set to nil if the policy can be evaluated, or it
/// contains error information if policy evaluation is not possible.
///
/// @return YES if the policy can be evaluated, NO otherwise.
@available(iOS 8.0, *)
open func canEvaluatePolicy(_ policy: LAPolicy, error: NSErrorPointer) -> Bool
在调用 evaluatePolicy
之前必须调用这个方法, 来判断是否支持预设的验证条件
/// Evaluates the specified policy.
///
/// @discussion Policy evaluation may involve prompting user for various kinds of interaction
/// or authentication. Actual behavior is dependent on evaluated policy, device type,
/// and can be affected by installed configuration profiles.
///
/// Be sure to keep a strong reference to the context while the evaluation is in progress.
/// Otherwise, an evaluation would be canceled when the context is being deallocated.
///
/// The method does not block. Instead, the caller must provide a reply block to be
/// called asynchronously when evaluation finishes. The block is executed on a private
/// queue internal to the framework in an unspecified threading context. Other than that,
/// no guarantee is made about which queue, thread, or run-loop the block is executed on.
///
/// Implications of successful policy evaluation are policy specific. In general, this
/// operation is not idempotent. Policy evaluation may fail for various reasons, including
/// user cancel, system cancel and others, see LAError codes.
///
/// @param policy Policy to be evaluated.
///
/// @param reply Reply block that is executed when policy evaluation finishes.
/// success Reply parameter that is YES if the policy has been evaluated successfully or
/// NO if the evaluation failed.
/// error Reply parameter that is nil if the policy has been evaluated successfully, or it
/// contains error information about the evaluation failure.
///
/// @param localizedReason Application reason for authentication. This string must be provided in correct
/// localization and should be short and clear. It will be eventually displayed in
/// the authentication dialog subtitle for Touch ID or passcode. The name of the
/// calling application will be displayed in title, so it should not be duplicated here.
///
/// This parameter is mostly ignored by Face ID authentication. Face ID will show
/// generic instructions unless a customized fallback title is provided in
/// localizedFallbackTitle property. For that case, it will show the authentication
/// reason so that the instructions can be made consistent with the custom button
/// title. Therefore, you should make sure that users are already aware of the need
/// and reason for Face ID authentication before they have triggered the policy evaluation.
///
/// @warning localizedReason parameter is mandatory and the call will throw NSInvalidArgumentException if
/// nil or empty string is specified.
///
/// @warning Applications should also supply NSFaceIDUsageDescription key in the Info.plist. This key identifies
/// a string value that contains a message to be displayed to users when the app is trying to use
/// Face ID for the first time. Users can choose to allow or deny the use of Face ID by the app before
/// the first use or later in Face ID privacy settings. When the use of Face ID is denied, evaluations
/// will fail with LAErrorBiometryNotAvailable.
///
/// @see LAError
///
/// Typical error codes returned by this call are:
/// @li LAErrorUserFallback if user tapped the fallback button
/// @li LAErrorUserCancel if user has tapped the Cancel button
/// @li LAErrorSystemCancel if some system event interrupted the evaluation (e.g. Home button pressed).
@available(iOS 8.0, *)
open func evaluatePolicy(_ policy: LAPolicy, localizedReason: String, reply: @escaping (Bool, Error?) -> Void)
这里需要特别注意的是, 不能在 reply
回调里再次调用 canEvaluatePolicy
方法, 否则会造成 死锁
连续验证失败超过预定次数后, 将不会再调用 reply
回调. 这点需要注意
其中包含一个用于判断当前机器是拥有何种 biometryType
的属性.
/// The device does not support biometry.
/// The device supports Touch ID.
/// The device supports Face ID.
/// Indicates the type of the biometry supported by the device.
///
/// @discussion This property is set when canEvaluatePolicy has been called for a biometric policy.
/// The default value is LABiometryTypeNone.
@available(iOS 11.0, *)
open var biometryType: LABiometryType { get }
它是在调用 canEvaluatePolicy
方法后, 被设值
类型如下:
- none
- touchID
- faceID
@available(iOS 11.0, *)
public enum LABiometryType : Int {
/// The device does not support biometry.
@available(iOS 11.2, *)
case none
/// The device does not support biometry.
@available(iOS, introduced: 11.0, deprecated: 11.2, renamed: "LABiometryType.none")
public static var LABiometryNone: LABiometryType { get }
/// The device supports Touch ID.
case touchID
/// The device supports Face ID.
case faceID
}
/// Authentication was not successful, because user failed to provide valid credentials.
case authenticationFailed
/// Authentication was canceled by user (e.g. tapped Cancel button).
case userCancel
/// Authentication was canceled, because the user tapped the fallback button (Enter Password).
case userFallback
/// Authentication was canceled by system (e.g. another application went to foreground).
case systemCancel
/// Authentication could not start, because passcode is not set on the device.
case passcodeNotSet
/// Authentication could not start, because Touch ID is not available on the device.
@available(iOS, introduced: 8.0, deprecated: 11.0, message: "use LAErrorBiometryNotAvailable")
case touchIDNotAvailable
/// Authentication could not start, because Touch ID has no enrolled fingers.
@available(iOS, introduced: 8.0, deprecated: 11.0, message: "use LAErrorBiometryNotEnrolled")
case touchIDNotEnrolled
/// Authentication was not successful, because there were too many failed Touch ID attempts and
/// Touch ID is now locked. Passcode is required to unlock Touch ID, e.g. evaluating
/// LAPolicyDeviceOwnerAuthenticationWithBiometrics will ask for passcode as a prerequisite.
@available(iOS, introduced: 9.0, deprecated: 11.0, message: "use LAErrorBiometryLockout")
case touchIDLockout
/// Authentication was canceled by application (e.g. invalidate was called while
/// authentication was in progress).
@available(iOS 9.0, *)
case appCancel
/// LAContext passed to this call has been previously invalidated.
@available(iOS 9.0, *)
case invalidContext
/// Authentication could not start, because biometry is not available on the device.
@available(iOS 11.0, *)
public static var biometryNotAvailable: LAError.Code { get }
/// Authentication could not start, because biometry has no enrolled identities.
@available(iOS 11.0, *)
public static var biometryNotEnrolled: LAError.Code { get }
/// Authentication was not successful, because there were too many failed biometry attempts and
/// biometry is now locked. Passcode is required to unlock biometry, e.g. evaluating
/// LAPolicyDeviceOwnerAuthenticationWithBiometrics will ask for passcode as a prerequisite.
@available(iOS 11.0, *)
public static var biometryLockout: LAError.Code { get }
/// Authentication failed, because it would require showing UI which has been forbidden
/// by using interactionNotAllowed property.
@available(iOS 8.0, *)
case notInteractive
这些错误就不细说了.
主要赘述一下 notInteractive
: 有时候在后台调起 App 时, 如果申请的时机早于 UIApplicationDidBecomeActiveNotification
之前, 则有可能会报这个错误. 换而言之: 并不能在后台调用验证功能, 其实想想也明白, 如果在后台调用, 弹出验证, 用户哪知道是什么 App 弹出的.🤪