基于Face ID/Touch ID的App防护:临时中断时跳过身份验证的实现
实现临时中断场景跳过生物识别验证的方案
这个需求很贴合用户体验,核心就是要区分临时失去焦点和真正进入后台两种场景,下面给你一套具体的实现思路和代码示例:
一、先明确两种场景的差异
iOS里应用进入非活跃状态分两种情况:
- 临时中断:比如来电弹窗、下拉控制中心/通知中心、多任务预览(但没切换到其他App),此时应用只是短暂失焦,不会进入后台状态。
- 需验证的场景:用户切换到其他App、锁屏、按Home键退出,此时应用会真正进入后台,必须触发验证。
我们的目标就是:只在应用进入后台时标记需要验证,临时失焦则跳过。
二、具体实现逻辑(以AppDelegate为例,iOS13+可适配SceneDelegate)
1. 定义状态标记变量
在AppDelegate中添加两个私有变量,用来跟踪应用状态:
import UIKit import LocalAuthentication class AppDelegate: UIResponder, UIApplicationDelegate { // 标记是否需要跳过生物识别验证 private var shouldSkipBiometricAuth = false // 记录应用是否进入过后台 private var didEnterBackground = false // 其他初始化代码... }
2. 监听应用状态变化通知
在didFinishLaunchingWithOptions中注册通知监听,或者直接重写AppDelegate的生命周期方法:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 注册状态监听通知(也可以直接重写AppDelegate的对应方法) NotificationCenter.default.addObserver(self, selector: #selector(handleAppResignActive), name: UIApplication.willResignActiveNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleAppEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleAppBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) return true }
3. 实现状态判断逻辑
@objc private func handleAppResignActive() { // 默认需要验证,除非是临时失焦场景 shouldSkipBiometricAuth = false // 如果当前应用还没进入后台,说明是临时中断(来电、控制中心等) if UIApplication.shared.applicationState != .background { shouldSkipBiometricAuth = true } } @objc private func handleAppEnterBackground() { // 进入后台,标记必须验证 didEnterBackground = true shouldSkipBiometricAuth = false // 这里可以执行锁定逻辑,比如清理敏感数据、切换到解锁页 lockApp() } @objc private func handleAppBecomeActive() { // 只有进入过后台,或者不是临时中断场景,才触发验证 if didEnterBackground || !shouldSkipBiometricAuth { triggerBiometricAuth() } // 重置后台标记 didEnterBackground = false }
4. 补充核心辅助方法
// 锁定应用:比如切换到解锁页面 private func lockApp() { guard let window = UIApplication.shared.windows.first else { return } let unlockVC = UnlockViewController() // 你的解锁页面 window.rootViewController = unlockVC } // 触发生物识别验证 private func triggerBiometricAuth() { let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) { let reason = "请验证身份以继续使用应用" context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { [weak self] success, error in DispatchQueue.main.async { if success { // 验证成功,恢复主应用流程 self?.restoreApp() } else { // 验证失败,保持锁定状态 self?.lockApp() } } } } else { // 不支持生物识别,引导用户用密码验证或直接锁定 lockApp() } } // 恢复应用到正常状态 private func restoreApp() { guard let window = UIApplication.shared.windows.first else { return } let mainVC = MainTabBarController() // 你的主页面 window.rootViewController = mainVC }
三、iOS13+ SceneDelegate适配
如果你的应用使用SceneDelegate,逻辑完全一致,只是把方法替换成SceneDelegate的生命周期方法:
class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? private var shouldSkipBiometricAuth = false private var didEnterBackground = false func sceneWillResignActive(_ scene: UIScene) { shouldSkipBiometricAuth = false if let scene = scene as? UIWindowScene, scene.application.applicationState != .background { shouldSkipBiometricAuth = true } } func sceneDidEnterBackground(_ scene: UIScene) { didEnterBackground = true shouldSkipBiometricAuth = false lockApp() } func sceneDidBecomeActive(_ scene: UIScene) { if didEnterBackground || !shouldSkipBiometricAuth { triggerBiometricAuth() } didEnterBackground = false } // 其余lockApp、triggerBiometricAuth、restoreApp方法和上面一致 }
四、额外注意点
- 多任务预览场景:用户上滑进入多任务但没切换App,属于临时中断,上述逻辑会自动跳过验证。
- 锁屏场景:锁屏会触发
didEnterBackground,所以一定会要求验证,符合安全需求。 - 通知弹窗:通知弹窗只会让应用失焦,不会进入后台,回到应用时无需验证,体验更顺畅。
内容的提问来源于stack exchange,提问作者Harry Ng
相关产品推荐
相关产品推荐

