如何以编程方式检查“Face Id”和“Touch Id”的支持

时间:2017-10-23 10:49:36

标签: ios ios11 touch-id face-id localauthentication

我已将LocalAuthentication集成到我的应用安全目的,该目的一直支持'Touch Id'支持。但是现在,苹果最近还添加了'Face Id'身份验证。

如何检查设备支持哪种类型的身份验证。触摸ID或面部识别码?

14 个答案:

答案 0 :(得分:35)

我一直在努力让这个工作,并发现我需要使用LAContext的单个实例并需要调用 LAContextInstance .canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,error:nil )在获取biometryType之前。这是我的最终代码,支持旧的iOS版本:

input {
    background-color: red;

    &:checked {

        label & {
            background-color: green;
        }
    }
}

答案 1 :(得分:18)

使用Xcode 9,查看LocalAuthentication -> LAContext -> LABiometryType

LABiometryType 是一个枚举,其值如附加图像

enter image description here

您可以在Touch ID和FaceID之间检查设备支持的身份验证类型,或者不检查。

修改

Apple已更新此枚举 LABiometryType 的值。 none现已弃用

enter image description here

答案 2 :(得分:7)

我非常喜欢扩展。我对这个答案的措辞有些不同。本质是一样的。这是一个插件扩展。

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
        }
    }
}

像这样使用:

var currentType = LAContext().biometricType

答案 3 :(得分:5)

目标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;
    }
}

答案 4 :(得分:4)

这是通过属性的另一种方式(例如,在您的访问实例上)。

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
        }
    }
}

答案 5 :(得分:4)

人脸ID 在iOS 11中可用,而iPhone X默认情况下是iOS 11附带的。他们在LocalAuth框架中添加了一个“ biometryType”属性,该属性使您能够检测设备上是否存在Face ID。

/// 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
}

答案 6 :(得分:4)

这是我的“帮助程序类”,它还包括密码

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
        }
    }
}

答案 7 :(得分:1)

此代码在Xcode from .block import *-9.2上构建时没有警告(请参见9.4的注释):

9.1

答案 8 :(得分:1)

来自@Markicevic扩展名,但忽略了用户未注册等情况……

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
    }
}

}

答案 9 :(得分:1)

我为本地身份验证创建了一个单例类,因为它有助于使用整个应用程序的static属性来初始化实例。

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
        }
    }
}

实施:

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

答案 10 :(得分:1)

-(BOOL)faceIDAvailable {
        LAContext *myContext = [[LAContext alloc] init];
        NSError *authError = nil;

        if (@available(iOS 11.0, *)) {
            if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&authError] && myContext.biometryType == LABiometryTypeFaceID) {
                return true;
            }
        }
      return false;

}
-(BOOL)touchIDAvailable {
        LAContext *myContext = [[LAContext alloc] init];
        NSError *authError = nil;

        if (@available(iOS 11.0, *)) {
            if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&authError] && myContext.biometryType == LABiometryTypeTouchID) {
                return true;
            }
        }
      return false;

}

答案 11 :(得分:0)

快速更新5,开关流量需要默认条件。

rvs

测试案例在下面

import Foundation
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 through fabric
            return .none
        }

        if #available(iOS 11.0, *) {
            switch self.biometryType {
            case .touchID:
                return .touchID
            case .faceID:
                return .faceID
            default:
                return .none
            }
        }

        return self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
    }

}

如果要在模拟器中进行测试,则需要注册touchId / faceId。
模拟器>硬件>触摸ID /面部ID>已注册。 enter image description here

答案 12 :(得分:0)

请参阅为“使用面部ID或触摸ID将用户登录到您的应用程序” 中提供的Apple示例代码。

Apple示例代码链接- https://docs-assets.developer.apple.com/published/fbfd13f4d9/LoggingAUserIntoYourAppWithFaceIDOrTouchID.zip

在下面的链接上阅读示例代码的详细说明。 https://developer.apple.com/documentation/localauthentication/logging_a_user_into_your_app_with_face_id_or_touch_id

答案 13 :(得分:0)

开始在 12 Pro 上测试一些新应用,发现我发布的应用只有 Touch ID 而没有 Face ID。

我来到这里看到了这一切,所以我开始尝试更改我的 Touch ID 代码,但我需要做的就是将隐私密钥添加到 info.plist。

信息属性列表➕

然后向下滚动到:Privacy- Face ID Usage Description, (Type: String), (Value: YES)

太简单了?