SwiftUI使用TouchID和FaceID
SwiftUI使用TouchID和FaceID

SwiftUI使用TouchID和FaceID

在 SwiftUI 中,可以通过集成 LocalAuthentication 框架来使用 Touch ID 和 Face ID。这些功能被统称为 生物识别认证,适用于设备锁定、应用保护、数据安全等场景。

实现步骤

1、导入框架

引入 LocalAuthentication 框架以访问生物识别认证功能。

import LocalAuthentication

2、创建认证逻辑

使用 LAContext 来执行生物识别认证。

3. 集成到 SwiftUI 界面

将认证逻辑绑定到 SwiftUI 的视图中,通过按钮触发或其他条件自动执行。

完整代码示例

以下是一个使用 Touch ID 或 Face ID 的示例应用:

import SwiftUI
import LocalAuthentication

struct ContentView: View {
    @State private var isAuthenticated = false
    @State private var errorMessage = ""
    
    var body: some View {
        VStack(spacing: 20) {
            if isAuthenticated {
                Text("Welcome! 🎉")
                    .font(.largeTitle)
                    .foregroundColor(.green)
            } else {
                Text("Please authenticate")
                    .font(.title)
                    .foregroundColor(.red)
                Button(action: authenticate) {
                    Label("Unlock with Biometrics", systemImage: "faceid")
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .clipShape(Capsule())
                }
                if !errorMessage.isEmpty {
                    Text("Error: \(errorMessage)")
                        .foregroundColor(.red)
                        .font(.footnote)
                }
            }
        }
        .padding()
    }
    
    func authenticate() {
        let context = LAContext()
        var error: NSError?

        // 检查设备是否支持生物识别
        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
            let reason = "Authenticate to access your account"

            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
                DispatchQueue.main.async {
                    if success {
                        isAuthenticated = true
                        errorMessage = ""
                    } else {
                        isAuthenticated = false
                        errorMessage = authenticationError?.localizedDescription ?? "Unknown error"
                    }
                }
            }
        } else {
            // 设备不支持生物识别
            DispatchQueue.main.async {
                errorMessage = error?.localizedDescription ?? "Biometric authentication is not available"
            }
        }
    }
}

#Preview {
    ContentView()
}

代码功能

1、检查当前设备是否支持生物识别验证。

2、如果支持,则调用生物识别功能进行身份验证。

3、根据验证结果(成功或失败),执行不同的逻辑。

4、如果设备不支持生物识别,则返回错误信息。

代码解析

这段 Swift 代码实现了设备生物识别验证(如 Face ID 或 Touch ID)的逻辑,主要是用来检查设备是否支持生物识别验证,并根据用户的验证结果执行相应操作。以下是详细解析:

1、创建生物识别上下文

let context = LAContext()
var error: NSError?

LAContext 是 LocalAuthentication 框架中的类,用来管理身份验证的上下文环境。

error 是一个可选的 NSError,用于存储设备不支持生物识别验证时的错误信息。

2、检查设备是否支持生物识别

if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)

canEvaluatePolicy 是用来检查设备是否支持特定的身份验证策略。

参数 .deviceOwnerAuthenticationWithBiometrics 表示使用生物识别(如 Face ID 或 Touch ID)验证用户身份。

如果设备支持生物识别功能,canEvaluatePolicy 返回 true;否则返回 false 并将错误信息存储在 error 中。

3、调用生物识别验证

context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
    DispatchQueue.main.async {
        if success {
            isAuthenticated = true
            errorMessage = ""
        } else {
            isAuthenticated = false
            errorMessage = authenticationError?.localizedDescription ?? "Unknown error"
        }
    }
}

1)evaluatePolicy 方法

发起生物识别验证,弹出系统提供的身份验证界面。

参数

.deviceOwnerAuthenticationWithBiometrics:生物识别验证策略。

localizedReason:向用户解释为什么需要验证(会显示在系统弹出的验证对话框中)。

2)闭包返回两个参数

success:一个布尔值,表示验证是否成功。

authenticationError:验证失败时的错误信息。

3)DispatchQueue.main.async

确保 UI 更新在主线程中完成。

4)成功时的逻辑

isAuthenticated = true
errorMessage = ""

5)失败时的逻辑

isAuthenticated = false
errorMessage = authenticationError?.localizedDescription ?? "Unknown error"

4、处理设备不支持生物识别的情况

DispatchQueue.main.async {
    errorMessage = error?.localizedDescription ?? "Biometric authentication is not available"
}

如果设备不支持生物识别,进入 else 块。

更新 errorMessage,告知用户设备不支持生物识别验证,并提供错误的具体描述。

生物识别认证报错

在首次识别时,可能存在无法识别认证的情况,Xcode报错输出:

This app has crashed because it attempted to access privacy-sensitive data without a usage description.  The app's Info.plist must contain an NSFaceIDUsageDescription key with a string value explaining to the user how the app uses this data.

这是因为应用没有在Info.plist文件中声明使用Face ID的权限描述,因此iOS系统拒绝了对生物识别功能的访问。这是一个必要的步骤,否则应用会崩溃。

解决步骤

1、找到项目的Info.plist文件。

2、在Info.plist文件中新增

Privacy - Face ID Usage Description

我们需要使用 Face ID 来解锁您的数据。 // Value值

Privacy – Face ID Usage Description 是一个键(Key),它代表你的应用请求使用 Face ID 功能时显示的权限描述。

右侧的 Value 列是键的对应值,也就是应用向用户解释为什么需要使用 Face ID 的具体内容。

3、重新启动应用,问题得到解决。

用户控制生物识别认证

1、添加控制生物识别的布尔值

    @AppStorage("isBiometricEnabled") private var isBiometricEnabled = false

    2、给生物识别添加判断,检查是否启用识别变量

    // 检查用户是否启用了生物识别验证
    guard isBiometricEnabled else {
        print("Biometric authentication is disabled by the user.")
        return
    }

    3、添加生物识别控制按钮

    Toggle("Enable Biometric Authentication", isOn: $isBiometricEnabled)
    .padding()

    修改后,实现用户通过按钮控制生物识别认证功能。

    实现效果

    完整代码示例

    import SwiftUI
    import LocalAuthentication
    
    struct ContentView: View {
        @State private var isUnlocked = false
        @AppStorage("isBiometricEnabled") private var isBiometricEnabled = false
    
        func authenticate() {
            let context = LAContext()
            var error: NSError?
    
            // 检查用户是否启用了生物识别验证
            guard isBiometricEnabled else {
                print("Biometric authentication is disabled by the user.")
                return
            }
    
            // 检查是否可以使用生物识别
            if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
                let reason = "We need to unlock your data."
    
                context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
                    DispatchQueue.main.async {
                        if success {
                            self.isUnlocked = true
                        } else {
                            print("Authentication failed: \(authenticationError?.localizedDescription ?? "Unknown error")")
                        }
                    }
                }
            } else {
                print("Biometric authentication is not available: \(error?.localizedDescription ?? "Unknown error")")
            }
        }
    
        var body: some View {
            NavigationView {
                VStack {
                    if isUnlocked {
                        Text("Unlocked")
                            .font(.largeTitle)
                            .foregroundColor(.green)
                    } else {
                        Text("Locked")
                            .font(.largeTitle)
                            .foregroundColor(.red)
                    }
    
                    Toggle("Enable Biometric Authentication", isOn: $isBiometricEnabled)
                        .padding()
    
                    Button("Authenticate") {
                        authenticate()
                    }
                    .padding()
                }
                .navigationTitle("Biometric Settings")
            }
        }
    }
    
    #Preview {
        ContentView()
    }

    生物识别验证的备选方案

    如果设备不支持生物识别或者用户拒绝验证,可以提供密码作为备选方案:

    context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error)

    deviceOwnerAuthentication 的含义

    .deviceOwnerAuthentication 是一种更通用的身份验证策略。

    它不仅支持生物识别验证(如 Face ID 或 Touch ID),还支持设备密码(PIN、图案或设备解锁密码)作为备选方案。

    如果设备不支持生物识别,或者用户多次失败,系统会自动回退到设备密码验证。

    如何使用

    可以将 .deviceOwnerAuthentication 添加到现有代码中,作为生物识别验证的备选方案。例如:

    func authenticate() {
        let context = LAContext()
        var error: NSError?
    
        // 检查设备是否支持生物识别或设备密码验证
        if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
            let reason = "Authenticate to access your account"
    
            context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, authenticationError in
                DispatchQueue.main.async {
                    if success {
                        isAuthenticated = true
                        errorMessage = ""
                    } else {
                        isAuthenticated = false
                        errorMessage = authenticationError?.localizedDescription ?? "Unknown error"
                    }
                }
            }
        } else {
            // 设备不支持生物识别或密码验证
            DispatchQueue.main.async {
                errorMessage = error?.localizedDescription ?? "Authentication is not available"
            }
        }
    }

    1、替换 deviceOwnerAuthenticationWithBiometrics

    将策略从 .deviceOwnerAuthenticationWithBiometrics 替换为 .deviceOwnerAuthentication:

    如果用户设备支持生物识别,会优先使用生物识别。

    如果用户多次失败,或者设备不支持生物识别,系统会回退到密码验证。

    2、用户体验改进

    用户在生物识别验证失败后,可以直接输入密码继续验证,而无需额外处理逻辑。

    即使用户的设备完全不支持生物识别(例如旧设备),仍然可以通过密码验证。

    注意事项

    1、Face ID/Touch ID 描述不再适用

    在弹出的验证对话框中,localizedReason 会展示给用户。如果用户用的是密码验证,这个描述可能需要更通用的描述,例如:

    进行身份验证以安全访问您的帐户

    2、错误处理

    在用户取消或失败后,可以检查 authenticationError,并根据错误类型提供具体提示。例如:

    LAError.userCancel:用户取消验证。

    LAError.authenticationFailed:身份验证失败。

    3、回退逻辑

    如果用户设备完全不支持 .deviceOwnerAuthentication(非常少见),可以提示用户使用另一种方法访问应用(例如注册账号或输入固定密码)。

    参考资料

    Using Touch ID and Face ID with SwiftUI:https://www.hackingwithswift.com/books/ios-swiftui/using-touch-id-and-face-id-with-swiftui

    如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

    发表回复

    您的电子邮箱地址不会被公开。 必填项已用 * 标注