Проверка подлинности FaceID никогда не завершается ошибкой политики «authenticationFailed» на реальном iPhoneX - PullRequest
0 голосов
/ 29 ноября 2018

Запустив предоставленный код (простое IBAction, запускаемое кнопкой в ​​ViewController) на моем реальном устройстве iPhoneX, я не могу попасть в ошибку errorPolicy: LAError.authenticationFailed из-за сбоя распознавания FaceIDбольше раз.Этот случай управляется в коде с помощью функцииvaluPolicyErrorMessage ().

Используя вместо этого симулятор, я могу попасть в LAError.authenticationFailed , выбрав 3 раза Оборудование -> FaceID -> Несоответствующее лицо , после первого предупреждения «Попробовать FaceID снова», но БЕЗ , нажав кнопку «Попробовать FaceID еще раз» на самом предупреждении: просто 3 раза повторить выбор Аппаратное обеспечение -> FaceID -> Несоответствующее Face .

Может кто-нибудь подсказать, что не так в моем коде?Я извиняюсь, если это довольно много, но я попытался сопоставить все возможные случаи и подслучаи.

Вот вам ссылка на этот проект: https://github.com/giurobrossi/testBiometricAuthentication.git

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func authButton(_ sender: Any) {

        let context = LAContext()

        if #available(iOS 10, *) {
            context.localizedCancelTitle = "Cancel"
        }

        var canEvaluateError: NSError?
        var message = ""

        if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &canEvaluateError) {
            if #available(iOS 11.0, *) {
                switch context.biometryType.rawValue {
                    case 0:
                        message = "Device doesn't have a biometry available"
                    case 1:
                        message = "Device has got TouchID"
                    case 2:
                        message = "Device has got FaceID"
                    default:
                        message = "biometry device not recognized"
                }
            } else {
                message = "Device is eligible to evaluate the authentication. (iOS < 11)"
            }
            //self.presentAlertMainThread(message: message)
            print(message)
            context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Let's authenticate!" ) { success, evaluateError in
                if success {
                    self.presentAlertMainThread(message: "Login succesful !")
                }
                else {
                    message = self.evaluatePolicyErrorMessage(errorCode: (evaluateError! as NSError).code)
                    self.presentAlertMainThread(message: message )
                    print("EvaluatePolicy Error: \(evaluateError!._code)")
                }
            }
        }
        else {
            message = canEvaluatePolicyErrorMessage(errorCode: (canEvaluateError?.code)!, context: context)
            self.presentAlertMainThread(message:  message)
            print("CanEvaluatePolicy Error: \(String(describing: canEvaluateError?.code ))")
        }
    }
}


extension ViewController {

    func presentAlertMainThread(message: String) {
        DispatchQueue.main.async(execute: {
            let alertController = UIAlertController(title: "Attenzione", message: message, preferredStyle: UIAlertControllerStyle.alert)
            self.present(alertController, animated: true, completion: nil)
            let defaultAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)
            alertController.addAction(defaultAction)
        })
    }

    func canEvaluatePolicyErrorMessage(errorCode: Int, context: LAContext) -> String {
        var message = ""
        if #available(iOS 11.0, *) {
            switch errorCode {
                // -6
                case LAError.biometryNotAvailable.rawValue:
                    switch context.biometryType.rawValue {
                        case 0: // non capita mail (iOS >= 11)
                            message = "Device does not have any biometry available"
                        case 1:
                            message = "Device has got TouchID but the permission is false"
                        case 2:
                            message = "Device has got FaceID but the permission is false"
                        default:
                            message = "biometry sensor not recognized"
                    }
                // TBD
                case LAError.biometryLockout.rawValue:
                        switch context.biometryType.rawValue {
                            case 0:
                                message = "Device does not have any biometry available"
                            case 1:
                                message = "Device has got TouchID but the biometry is locked"
                            case 2:
                                message = "Device has got FaceID but the biometry is locked"
                            default:
                                message = "biometry sensor not recognized"
                        }
                // -7
                case LAError.biometryNotEnrolled.rawValue:
                    switch context.biometryType.rawValue {
                        case 0:
                            message = "Device does not have any biometry available"
                        case 1:
                            message = "Device has got TouchID but the biometry is not enrolled"
                        case 2:
                            message = "Device has got FaceID but the biometry is not enrolled"
                        default:
                            message = "biometry sensor not recognized"
                    }
                default:
                    message = "Policy Error type not managed."
                }
        }
        else if #available(iOS 9.0, *) {
            switch errorCode {
                // TBD
                case LAError.touchIDLockout.rawValue:
                    if #available(iOS 11.0, *) {
                        switch context.biometryType.rawValue {
                            case 0:
                                message = "Device does not have any biometry available"
                            case 1:
                                message = "Device has got TouchID but the biometry is locked"
                            case 2:
                                message = "Device has got FaceID but the biometry is locked"
                            default:
                                message = "biometry sensor not recognized"
                        }
                    } else {
                        message = "Too much auth. attempts by TouchID (9.0 <= iOS < 11.0) - Auth. Blocked"
                    }
                // -6
                case LAError.touchIDNotAvailable.rawValue:
                    if #available(iOS 11.0, *) {
                        switch context.biometryType.rawValue {
                            case 0:
                                message = "Device does not have any biometry available"
                            case 1:
                                message = "Device has got TouchID but the permission is false"
                            case 2:
                                message = "Device has got FaceID but the permission is false"
                            default:
                                message = "biometry sensor not recognized"
                        }
                    } else {
                        message = "Device does not have TouchID available (9.0 <= iOS < 11.0)"
                    }
                // -7
                case LAError.touchIDNotEnrolled.rawValue:
                    if #available(iOS 11.0, *) {
                        switch context.biometryType.rawValue {
                            case 0:
                                message = "Device does not have any biometry available"
                            case 1:
                                message = "Device has got TouchID but the biometry is not enrolled"
                            case 2:
                                message = "Device has got FaceID but the biometry is not enrolled"
                            default:
                                message = "biometry sensor not recognized"
                        }
                    } else {
                        message = "TouchID not 'enrolled' (9.0 <= iOS < 11.0)"
                    }
                default:
                    message = "Policy Error type not managed."
            }
        }
        else {
            // 8.0 <= iOS < 9.0
            print("canEvaluatePolicy Error: \(errorCode.description)")
        }
        return message;
    }


    func evaluatePolicyErrorMessage(errorCode: Int) -> String {
        var message = ""
        if #available(iOS 9.0, *) {
            switch errorCode {
                // -1
                case LAError.authenticationFailed.rawValue:
                    message = "Authentication Failed"
                // -9
                case LAError.appCancel.rawValue:
                    message = "Authentication cancelled by the app"
                // TBD
                case LAError.invalidContext.rawValue:
                    message = "LAContext passed to this call has been previously invalidated"
                // TBD
                case LAError.notInteractive.rawValue:
                    message = "Authentication failed, because it would require showing UI which has been forbidden by using interactionNotAllowed property"
                // TBD
                case LAError.passcodeNotSet.rawValue:
                    message = "Passcode not set"
                // -4
                case LAError.systemCancel.rawValue:
                    message = "Authentication cancelled by iOS"
                // -2
                case LAError.userCancel.rawValue:
                    message = "Authentication cancelled by the user"
                // -3 
                case LAError.userFallback.rawValue:
                    message = "Fallback selected by the user
                default:
                    message = "Error not managed"
            }
        } else {
            message = "Failed Authentication (8.0 <= iOS < 9.0) - Code: \(errorCode.description)"
        }
        return message
    }
}
...