通过生物特征或者已经知道的密码验证用户。
许多用户依靠人脸识别(Face ID)或触摸识别(Touch ID)等生物特征认证来实现对设备的安全、轻松访问。作为备用选项,对于没有生物计量的设备,密码或密码也有类似的作用。使用LocalAuthentication框架在应用程序中利用这些机制,并扩展应用程序已经实现的身份验证过程。
为了最大限度地提高安全性,您的应用程序永远无法访问任何底层身份验证数据。例如,您无法访问任何指纹图像。Secure Enclave是一个基于硬件的安全处理器,与系统的其他部分隔离,它可以管理即使操作系统也无法访问的数据。相反,您可以指定一个特定的策略并提供消息,告诉用户您希望他们进行身份验证的原因。然后,该框架与Secure Enclave进行协调,以执行该行动。之后,您只收到一个布尔结果,指示身份验证成功或失败。
使用Face ID或Touch ID将用户登录到您的应用程序
使用生物特征认证补充您自己的认证方案,让用户轻松访问应用程序的敏感部分。
用户喜欢Touch ID和Face ID,因为这些身份验证机制可以让他们以最小的努力安全地访问设备。当您采用LocalAuthentication框架时,您可以简化典型情况下的用户身份验证体验,同时在生物特征不可用时提供备用选项。
设置面部ID使用说明
在任何使用生物特征的项目中,在应用程序的plist文件中包含NSFaceIDUsageDescription键。如果没有此密钥,系统将不允许您的应用程序使用Face ID。此密钥的值是系统在应用程序首次尝试使用Face时向用户显示的字符串。该字符串应明确说明应用程序需要访问此身份验证机制的原因。系统不需要对Touch ID进行类似的使用说明。
创建和配置上下文
您使用LAContext实例在应用程序中执行生物特征认证,该实例代理应用程序和Secure Enclave之间的交互。首先创建上下文:
var context = LAContext()
您可以自定义上下文使用的消息传递,以引导用户完成流程。例如,您可以为显示在各种警报视图中的“取消”按钮设置自定义消息:
context.localizedCancelTitle = "Enter Username/Password"
这有助于用户理解,当他们点击按钮时,他们将恢复到您的正常身份验证过程。
测试策略可用性
在尝试进行身份验证之前,请通过调用canEvaluatePolicy(_:error:)方法进行测试,以确保您确实有能力进行身份验证:
var error: NSError? guard context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) else { print(error?.localizedDescription ?? "Can't evaluate policy") // Fall back to a asking for username and password. // ... return }
从LAPolicy枚举中选择要测试的值。该策略控制身份验证的行为。例如,此示例中使用的
LAPolicy.deviceOwnerAuthentication策略表明,当生物识别失败或不可用时,允许恢复到密码。或者,你可以指示deviceOwnerAuthenticationWithBiometrics策略,该策略不允许恢复到设备密码。
评估策略
准备好进行身份验证后,使用已测试的相同策略调用evaluatePolicy(_:localizedReason:reply:)方法:
Task { do { try await context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: "Log in to your account") state = .loggedin } catch let error { print(error.localizedDescription) // Fall back to a asking for username and password. // ... } }
对于Touch ID,或当用户输入密码时,系统将显示您在方法调用中提供的验证原因。对于应用程序要求用户进行身份验证的原因,必须提供一个明确的解释(针对您所在的任何地区进行本地化)。你的应用程序名称已经出现在你给出的原因之前,所以你不需要在消息中包含它。
(可选)调整用户界面以适应Face ID
除了生物特征扫描操作本身,Face ID与Touch ID有着重要的区别。当您的应用程序尝试使用Touch ID时,系统会显示一条消息,要求用户出示手指进行扫描。用户有时间考虑并可能通过取消提示来中止操作。当你的应用程序调用Face ID时,设备立即开始扫描用户的面部。用户没有最后的取消机会。为了适应这种行为差异,您可能需要提供不同的UI,具体取决于设备上可用的生物特征类型。
该示例应用程序提供了一个不同的用户界面,其中包括一个文本标签,其中包含一条消息,警告Face ID用户点击该按钮会立即进行Face ID扫描。该应用程序默认隐藏标签,仅对当前已注销的具有Face ID的用户显示标签。具有Touch ID(或根本没有生物测量)的用户不需要该信息,因为他们可以在扫描实际发生之前取消操作。
您可以通过读取上下文的biometryType参数来测试设备支持的生物测量类型:
faceIDLabel.isHidden = (state == .loggedin) || (context.biometryType != .faceID)
仅在对上下文运行canEvaluatePolicy(_:error:)方法至少一次后,此参数才包含有意义的值。
提供生物统计学的后备方案
由于各种原因,身份验证有时会失败或不可用:
- 用户的设备没有Touch ID或Face ID。
- 用户未注册生物识别,或没有密码集。
- 用户取消操作。
- 触摸ID或面部ID无法识别用户。
- 您以前通过调用invalidate()方法使上下文无效。
有关可能的错误条件的完整列表,请参阅LAError.Code。
此示例应用程序未实现替代身份验证。在真实的应用程序中,如果您遇到本地身份验证错误,请返回到您自己的身份验证方案,例如询问用户名和密码。使用生物特征作为你已经在做的事情的补充。不要将生物特征作为唯一的身份验证选项。
LAContext
用于评估身份验证策略和访问控制的机制。
@interface LAContext : NSObject
您使用身份验证上下文来评估用户的身份,可以使用诸如Touch ID或Face ID之类的生物特征,也可以提供设备密码。上下文处理用户交互和Secure Enclave接口,Secure Enclave是管理生物特征数据的底层硬件元素。您创建并配置上下文,并要求它执行身份验证。然后,您将收到一个异步回调,该回调提供身份验证成功或失败的指示,以及一个错误实例,说明失败的原因(如果有的话)。
注意
如果应用程序允许生物特征认证,请在应用程序的Info.plist文件中包含NSFaceIDUsageDescription密钥。否则,授权请求可能会失败。
canEvaluatePolicy:error:
评估是否可以对给定策略进行身份验证。
- (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError * _Nullable *)error;
参数
policy:要评估的策略。
error:如果该方法失败,它将使用此参数返回一个错误,详细说明错误所在。
为此参数指定nil以忽略任何错误。
返回值
如果可以评估策略,则为“是”,否则为“否”。
某些策略强制要求在进行身份验证之前必须满足这些要求。例如,如果禁用了Touch ID或Face ID,则需要生物识别的策略无法进行身份验证。此方法测试给定策略的所有先决条件。
不要存储此方法的返回值,因为它可能会因系统中的更改而更改。例如,用户可以在调用此方法后禁用Touch ID。然而,报告的值在应用程序进入后台之前保持一致。
注意
不要在evaluatePolicy:localizedReason:reply:方法的回复块中调用此方法,因为这可能会导致死锁。
LAPolicy
可用的本地身份验证策略集。
typedef enum LAPolicy : NSInteger { ... } LAPolicy;
枚举值
LAPolicyDeviceOwnerAuthenticationWithBiometrics:使用生物测量进行用户身份验证。
LAPolicyDeviceOwnerAuthenticationWithBiometrics = kLAPolicyDeviceOwnerAuthenticationWithBiometrics
调用evaluatePolicy:localizedReason:reply:
方法时,使用LAPolicyDeviceOwnerAuthenticationWithBiometrics策略来使用生物特征对用户进行身份验证。
如果Touch ID或Face ID不可用或未注册,则策略评估失败。三次Touch ID尝试失败后,评估也失败。在两次失败的Face ID尝试后,系统提供了一个回退选项,但停止尝试使用Face ID进行身份验证。在连续五次失败尝试后,触摸ID和Face ID身份验证将在系统范围内禁用,即使尝试跨越多个评估呼叫。发生这种情况时,系统要求用户输入设备密码以重新启用生物测量。
在认证过程中,系统为用户提供一个认证对话框,用于每次尝试使用Touch ID进行认证,或在任何失败的Face ID尝试之后。该对话框包含一个取消按钮,其标题可通过设置localizedCancelTitle属性自定义。如果用户点击取消按钮,策略评估将失败,并显示userCancel错误。
在第一次Touch ID尝试失败或第二次Face ID尝试失败后,验证对话框还显示后退按钮。通过设置localizedFallbackTitle属性,可以自定义回退按钮的标题。如果用户点击回退按钮,策略评估将失败,并显示userFallback错误。在这种情况下,你的应用程序应该提供一种验证用户的替代机制,比如询问PIN或密码。
要让系统通过询问设备密码(在iOS或watchOS中)或用户密码(在macOS中)来处理回退选项,请改用LAPolicyDeviceOwnerAuthentication策略。
LAPolicyDeviceOwnerAuthentication:使用生物计量、Apple Watch或设备密码进行用户身份验证。
LAPolicyDeviceOwnerAuthentication = kLAPolicyDeviceOwnerAuthentication
调用evaluatePolicy:localizedReason:reply:method
时,您使用LAPolicyDeviceOwnerAuthentication策略在iOS中使用生物特征或密码对用户进行身份验证。
如果生物测量可用、已注册且未禁用,系统将首先使用该方法。当这些选项不可用时,系统会提示用户输入设备密码或用户密码。
在iOS中,如果未启用设备密码,则策略评估失败,并显示错误passcodeNotSet。系统在6次尝试失败后禁用密码验证,尝试之间的延迟逐渐增加。
身份验证对话框包含一个带有默认标题的取消按钮,您可以使用localizedCancelTitle属性自定义该按钮,以及一个可以使用localedFallbackTitle属性自定义的回退按钮。当用户点击后退按钮时,系统将回复为询问设备密码或用户密码。当用户点击取消按钮时,评估将失败,并显示userCancel错误。
宏定义
kLAPolicyDeviceOwnerAuthenticationWithBiometrics:使用生物测量进行用户身份验证。
#define kLAPolicyDeviceOwnerAuthenticationWithBiometrics
kLAPolicyDeviceOwnerAuthentication:使用生物测量或设备密码进行用户身份验证。
#define kLAPolicyDeviceOwnerAuthentication
实例属性
biometryType:设备支持的生物特征认证类型。(iOS 11.0以上)
@property(nonatomic, readonly) LABiometryType biometryType;
使用此属性的值可确保您创建的任何与身份验证相关的用户提示与设备的生物特征功能相匹配。例如,如果此属性的值为LABiometryTypeFaceID,则不要在身份验证提示中引用Touch ID。
只有在调用canEvaluatePolicy:error:方法后才设置此属性,并且无论调用返回什么都会设置此属性。默认值为LABiometryTypeNone。
枚举值
LABiometryTypeNone:不支持生物测量类型。(iOS 11.2以上)
LABiometryTypeNone
LABiometryTypeFaceID:设备支持Face ID。(iOS 11.0以上)
LABiometryTypeFaceID
LABiometryTypeTouchID:设备支持Touch ID。(iOS 11.0以上)
LABiometryTypeTouchID
evaluatePolicy:localizedReason:reply:
评估指定的策略。
- (void)evaluatePolicy:(LAPolicy)policy localizedReason:(NSString *)localizedReason reply:(void (^)(BOOL success, NSError *error))reply;
参数
policy:要评估的策略。
localizedReason:应用程序提供了请求身份验证的原因,该原因显示在向用户显示的身份验证对话框中。
reply:策略评估完成时执行的关闭。这是在未指定的线程上下文中在框架内部的私有队列上进行评估的。不能在此块中调用canEvaluatePolicy:error:,因为这样做可能会导致死锁。
success:如果策略评估成功,则为“是”,否则为“否”。
error:如果策略评估成功,则为nil,否则应向用户显示错误对象。
此方法异步计算身份验证策略。评估策略可能涉及提示用户进行各种交互或认证。实际行为取决于评估的策略和设备类型。该行为也会受到已安装的配置文件的影响。
要控制支持它的设备上的身份验证提示,请在调用此方法之前将关联的本地身份验证上下文附加到LAAuthenticationView实例。
在身份验证对话框中显示给用户的本地化字符串中,提供身份验证请求的明确原因,并描述结果操作。使信息简短明了,并以用户的语言提供。不要包含已经出现在验证对话框中的应用程序名称(在iOS中,在副标题中)。
不要以为以前成功的政策评估意味着未来的评估也会成功。策略评估可能因各种原因而失败,包括用户或系统取消。
evaluatedPolicyDomainState
评估的策略域的当前状态。
@property(nonatomic, nullable, readonly) NSData *evaluatedPolicyDomainState;
仅当生物特征策略的canEvaluatePolicy:error:方法成功或evaluatePolicy:localizedReason:reply:方法被调用并执行成功的生物特征身份验证时,此属性才会返回值。否则,返回nil。
返回的数据是不透明的结构。它可用于与此属性返回的其他值进行比较,以确定授权数据库是否已更新。然而,无法根据该数据确定变更的性质。
evaluateAccessControl:operation:localizedReason:reply:
计算给定操作的访问控制。
- (void)evaluateAccessControl:(SecAccessControlRef)accessControl operation:(LAAccessControlOperation)operation localizedReason:(NSString *)localizedReason reply:(void (^)(BOOL success, NSError *error))reply;
参数
accessControl:要评估的访问控制。
operation:要评估的访问控制的操作。
localizedReason:应用程序提供了请求身份验证的原因,该原因显示在向用户显示的身份验证对话框中。
reply:当访问控制评估完成时执行的一个块。在未指定的线程上下文中,在框架内部的私有队列上评估此块。
success:如果策略评估成功,则为true,否则为false。
error:如果策略评估成功,则为nil,否则应向用户显示错误对象。
此方法异步计算访问控制。评估访问控制可能涉及提示用户进行各种交互或认证。实际行为取决于访问控制和设备类型。它还可能受到安装的配置文件的影响。
您呈现给用户的本地化字符串应该提供一个明确的原因,说明您为什么请求他们对自己进行身份验证,以及您将基于该身份验证采取什么行动。该字符串应以用户的当前语言提供,并且应简短明了。它不应包含应用程序名称,因为它会出现在身份验证对话框的其他位置。在iOS中,这出现在对话框副标题中。
您不应认为访问控制的先前成功评估必然导致后续成功评估。访问控制评估可能因各种原因而失败,包括用户或系统取消。
LAError
策略评估失败时框架返回的错误代码。
typedef enum LAError : NSInteger { ... } LAError;
枚举值
LAErrorAppCancel:应用程序取消了身份验证。
LAErrorAppCancel = kLAErrorAppCancel
如果在身份验证过程中调用invalid方法,则会收到此错误。
LAErrorSystemCancel:系统取消了身份验证。
LAErrorSystemCancel = kLAErrorSystemCancel
如果另一个应用程序在您的应用程序显示身份验证对话框时出现在前台,则可能会发生这种情况。
LAErrorUserCancel:用户点击了身份验证对话框中的取消按钮。
LAErrorUserCancel = kLAErrorUserCancel
LAErrorUserFallback:用户点击了身份验证对话框中的回退按钮,但身份验证策略没有可用的回退。
LAErrorUserFallback = kLAErrorUserFallback
LAErrorBiometryNotEnrolled:用户没有注册的生物识别身份。(iOS 11.0以上)
LAErrorBiometryNotEnrolled = kLAErrorBiometryNotEnrolled
LAErrorPasscodeNotSet:设备上未设置密码。
LAErrorPasscodeNotSet = kLAErrorPasscodeNotSet
LAErrorBiometryNotAvailable:设备上没有生物识别功能。(iOS 11.0以上)
LAErrorBiometryNotAvailable = kLAErrorBiometryNotAvailable
LAErrorAuthenticationFailed:用户无法提供有效凭据。
LAErrorAuthenticationFailed = kLAErrorAuthenticationFailed
LAErrorBiometryLockout:生物识别被锁定,因为失败的尝试太多。(iOS 11.0以上)
LAErrorBiometryLockout = kLAErrorBiometryLockout
现在需要密码才能解锁生物测量。请改用LAPolicyDeviceOwnerAuthentication策略以允许使用密码。
LAErrorInvalidContext:上下文先前已无效。
LAErrorInvalidContext = kLAErrorInvalidContext
通过调用上下文的无效方法使其无效。