webentwicklung-frage-antwort-db.com.de

So prüfen Sie programmgesteuert die Unterstützung von 'Face Id' und 'Touch Id'

Ich habe LocalAuthentication für meine App-Sicherheitsfunktion integriert, die 'Touch Id' basierte Unterstützung unterstützt. Aber jetzt hat Apple vor kurzem die Authentifizierung mit 'Face Id' hinzugefügt.

Wie kann ich überprüfen, welche Art von Authentifizierung von einem Gerät unterstützt wird. Touch Id oder Face Id?

15
Krunal

Sehen Sie sich mit Xcode 9 LocalAuthentication -> LAContext -> LABiometryType an.

LABiometryType ist eine Aufzählung mit Werten wie im angefügten Bild

 enter image description here

Sie können prüfen, welcher Authentifizierungstyp zwischen Touch ID und FaceID oder keiner vom Gerät unterstützt wird.

Bearbeiten:

Apple hat die Werte für diese Aufzählung LABiometryType aktualisiert. none ist jetzt veraltet

 enter image description here

15
Surjeet

Ich hatte Probleme damit, dieses Problem zu lösen, und stellte fest, dass ich eine einzelne Instanz von LAContext verwenden und die LAContextInstance .canEvaluatePolicy (.deviceOwnerAuthenticationWithBiometrics, error: nil) aufrufen musste, bevor ich den biometryType erhielt. Hier ist mein endgültiger Code mit Unterstützung für ältere iOS-Versionen:

static func biometricType() -> BiometricType {
    let authContext = LAContext()
    if #available(iOS 11, *) {
        let _ = authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
        switch(authContext.biometryType) {
        case .none:
            return .none
        case .touchID:
            return .touch
        case .faceID:
            return .face
        }
    } else {
        return authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touch : .none
    }
}

enum BiometricType {
    case none
    case touch
    case face
}
30
leifdan01

Ziel c :) 

/** Only interesting devices are enumerated here. To change view constraints depending
 on screen height. Or the top notch for iPhone X
 */
typedef NS_ENUM(NSUInteger, BPDeviceType) {
    BPDeviceTypeUnknown,
    BPDeviceTypeiPhone4,
    BPDeviceTypeiPhone5,
    BPDeviceTypeiPhone6,
    BPDeviceTypeiPhone6Plus,
    BPDeviceTypeiPhone7,
    BPDeviceTypeiPhone7Plus,
    BPDeviceTypeiPhoneX,
    BPDeviceTypeiPad
};

+ (BPDeviceType)getDeviceType {
    double screenHeight = [[UIScreen mainScreen] bounds].size.height;
    if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad)
    {
        return BPDeviceTypeiPad;

    } else if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone)
    {
        if (@available(iOS 11, *)) {
            UIEdgeInsets insets = [UIApplication sharedApplication].delegate.window.safeAreaInsets;
            if (insets.top > 0) {
                return BPDeviceTypeiPhoneX;
            }
        }

        if(screenHeight == 480) {
            return BPDeviceTypeiPhone4;
        } else if (screenHeight == 568) {
            return BPDeviceTypeiPhone5;
        } else if (screenHeight == 667) {
            return BPDeviceTypeiPhone6;
        } else if (screenHeight == 736) {
            return BPDeviceTypeiPhone6Plus;
        }
    }
    return BPDeviceTypeUnknown;
}

+ (BOOL) isBiometricIDAvailable {
    if (![LAContext class]) return NO;

    LAContext *myContext = [[LAContext alloc] init];
    NSError *authError = nil;
    if (![myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
        NSLog(@"%@", [authError localizedDescription]);
        return NO;
    }
    return YES;
}

+ (BOOL) isTouchIDAvailable {
    if (![LAContext class]) return NO;

    LAContext *myContext = [[LAContext alloc] init];
    NSError *authError = nil;
    if (![myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
        NSLog(@"%@", [authError localizedDescription]);
        return NO;
        // if (authError.code == LAErrorTouchIDNotAvailable) {}
    }

    if (@available(iOS 11.0, *)) {
        if (myContext.biometryType == LABiometryTypeTouchID){
            return YES;
        } else {
            return NO;
        }
    } else {
        return YES;
    }
}

+ (BOOL) supportFaceID {
    return [BPDeviceInfo getDeviceType] == BPDeviceTypeiPhoneX;
}

+ (BOOL) isFaceIDAvailable {
    if (![LAContext class]) return NO;

    LAContext *myContext = [[LAContext alloc] init];
    NSError *authError = nil;
    if (![myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
        NSLog(@"%@", [authError localizedDescription]);
        return NO;
    }

    if (@available(iOS 11.0, *)) {
        if (myContext.biometryType == LABiometryTypeFaceID){
            return YES;
        } else {
            return NO;
        }
    } else {
        return NO;
    }
}
5
karim

Da bin ich ein großer Fan von Extension. Ich formuliere diese Antwort etwas anders. Essense ist das gleiche. Dies ist eine Drop-In-Erweiterung. 

import LocalAuthentication

extension LAContext {
    enum BiometricType: String {
        case none
        case touchID
        case faceID
    }

    var biometricType: BiometricType {
        var error: NSError?

        guard self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
            // Capture these recoverable error thru Crashlytics
            return .none
        }

        if #available(iOS 11.0, *) {
            switch self.biometryType {
            case .none:
                return .none
            case .touchID:
                return .touchID
            case .faceID:
                return .faceID
            }
        } else {
            return  self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
        }
    }
}

Verwenden Sie wie folgt: 

var currentType = LAContext().biometricType
4
Alix

Hier ist ein weiterer Weg über die Eigenschaft (z. B. auf Ihrer Zugriffsinstanz). 

import LocalAuthentication


enum BiometricType {
    case none
    case touchID
    case faceID
}

var biometricType: BiometricType {
    get {
        let context = LAContext()
        var error: NSError?

        guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
            print(error?.localizedDescription ?? "")
            return .none
        }

        if #available(iOS 11.0, *) {
            switch context.biometryType {
            case .none:
                return .none
            case .typeTouchID:
                return .touchID
            case .typeFaceID:
                return .faceID
            }
        } else {
            return  .touchID
        }
    }
}
4
Dren

Face ID ist unter iOS 11 verfügbar und iPhone X wird standardmäßig mit iOS 11 geliefert. Im LocalAuth-Framework wurde eine Eigenschaft 'biometryType' hinzugefügt, mit der Sie erkennen können, ob die Gesichts-ID auf dem Gerät verfügbar ist.

/// checks if face id is avaiable on device
func faceIDAvailable() -> Bool {
    if #available(iOS 11.0, *) {
        let context = LAContext()
        return (context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthentication, error: nil) && context.biometryType == .faceID)
    }
    return false
}
3
Usman Awan

Ich habe eine Singleton-Klasse für die lokale Authentifizierung erstellt, da sie die einmalige Initialisierung einer Instanz mithilfe der Eigenschaft static für die gesamte Anwendung erleichtert.

import Foundation
import LocalAuthentication

public class LocalAuthManager: NSObject {

    public static let shared = LocalAuthManager()
    private let context = LAContext()
    private let reason = "Your Request Message"
    private var error: NSError?

    enum BiometricType: String {
        case none
        case touchID
        case faceID
    }

    private override init() {

    }

    // check type of local authentication device currently support
    var biometricType: BiometricType {
        guard self.context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
            return .none
        }

        if #available(iOS 11.0, *) {
            switch context.biometryType {
            case .none:
                return .none
            case .touchID:
                return .touchID
            case .faceID:
                return .faceID
            }
        } else {
            return self.context.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil) ? .touchID : .none
        }
    }
}

Implementierung:

func checkAuth() {
     let authType = LocalAuthManager.shared.biometricType
        switch authType {
        case .none:
            print("Device not registered with TouchID/FaceID")
        case .touchID:
            print("Device support TouchID")
        case .faceID:
            print("Device support FaceID")
        }
 }
3
Vinayak Pal

Hier ist meine "Helfer-Klasse", sie enthält auch einen Passcode

enum BiometryType: String {
    case none = "None"
    case faceID = "Face ID"
    case touchID = "Touch ID"
    case passcode = "Passcode"
}


var biometryType: BiometryType {
    let myContext = LAContext()

    let hasAuthenticationBiometrics = myContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
    let hasAuthentication = myContext.canEvaluatePolicy(.deviceOwnerAuthentication, error: nil)

    if #available(iOS 11.0, *) {
        if hasAuthentication {
            if hasAuthenticationBiometrics {
                switch myContext.biometryType {
                case .none: return .none
                case .faceID: return .faceID
                case .touchID: return .touchID
                }
            } else {
                return .passcode
            }
        } else {
            return .none
        }
    } else {
        if hasAuthentication {
            if hasAuthenticationBiometrics {
                return .touchID
            } else {
                return .passcode
            }
        } else {
            return .none
        }
    }
}
2
Markicevic

Von der @Markicevic-Erweiterung, aber Fälle ignorieren, in denen der Benutzer nicht registriert ist usw.

extension LAContext {

enum BiometricType: String {
    case none = ""
    case touchID = "Touch ID"
    case faceID = "Face ID"
}

static var biometricType: BiometricType {
    var error: NSError?

    let context = LAContext()

    _ = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)

    if error?.code == LAError.Code.touchIDNotAvailable.rawValue {
        return .none
    }

    if #available(iOS 11.0, *) {
        switch context.biometryType {
        case .none:
            return .none
        case .touchID:
            return .touchID
        case .faceID:
            return .faceID
        }
    } else {
        return  context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
    }
}

}

1
Everton Cunha

Dieser Code wird ohne Warnungen für Xcode 9.2-9.4 erstellt (siehe Kommentare zu 9.1):

@objc let biometricsAuthPolicy = LAPolicy.deviceOwnerAuthenticationWithBiometrics

@objc func supportsFaceID() -> Bool {
    if #available(iOS 11.0, *) {
        return biometryType() == .faceID // return biometryType() == .typeFaceID for Xcode 9.1
    }
    return false
}

@objc func supportsTouchID() -> Bool {
    if #available(iOS 11.0, *) {
        return biometryType() == .touchID // return biometryType() == .typeTouchID for Xcode 9.1
    }

    let context = LAContext()
    return context.canEvaluatePolicy(biometricsAuthPolicy, error: nil)
}

@objc @available(iOS 11.0, *)
func biometryType() -> LABiometryType {
    var error: NSError?
    let context = LAContext()

    guard context.canEvaluatePolicy(biometricsAuthPolicy, error: &error) else {
        if #available(iOS 11.2, *) {
            return .none
        }
        return LABiometryType.LABiometryNone // return LABiometryType.none for Xcode 9.1
    }

    return context.biometryType
}
1
Victor Bogdan