Ios 如何以编程方式检查对';面Id';和';触摸Id';

Ios 如何以编程方式检查对';面Id';和';触摸Id';,ios,ios11,touch-id,face-id,localauthentication,Ios,Ios11,Touch Id,Face Id,Localauthentication,我已经为我的应用程序安全目的进行了集成,它一直支持基于的“触摸Id”支持。但现在,苹果最近也增加了基于脸Id的认证 如何检查设备支持哪种类型的身份验证。使用Xcode 9触摸Id或面部Id?,查看 LABiometryType是一个枚举,其值如所附图像所示 您可以在Touch ID和FaceID之间检查设备支持哪种身份验证类型,或者不支持 编辑: import LocalAuthentication extension LAContext { enum BiometricType:

我已经为我的应用程序安全目的进行了集成,它一直支持基于的“触摸Id”支持。但现在,苹果最近也增加了基于脸Id的认证

如何检查设备支持哪种类型的身份验证。使用Xcode 9触摸Id或面部Id?

,查看

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

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

编辑:

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 {
            return .none
        }

        if #available(iOS 11.0, *) {
            switch self.biometryType {
            case .none:
                return .none
            case .touchID:
                return .touchID
            case .faceID:
                return .faceID
            @unknown default:
                #warning("Handle new Biometric type") 
            }
        }
        
        return  self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
    }
}
Apple已更新此枚举的值LABiometryType现在不推荐使用none

使用Swift 5检查支持的生物识别类型的扩展:

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 {
            return .none
        }

        if #available(iOS 11.0, *) {
            switch self.biometryType {
            case .none:
                return .none
            case .touchID:
                return .touchID
            case .faceID:
                return .faceID
            @unknown default:
                #warning("Handle new Biometric type") 
            }
        }
        
        return  self.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) ? .touchID : .none
    }
}

我一直在努力实现这一点,发现我需要使用LAContext的一个实例,并需要在获取biometryType之前调用LaContedeStation.CaneValuePolicy(.deviceOwnerAuthenticationWithBiometrics,error:nil)。以下是我最后一段支持旧版iOS的代码:

import LocalAuthentication

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
}

下面是通过属性的另一种方式(例如,在access实例上)

目标C:)


此代码在Xcode
9.2
-
9.4
上生成时没有警告(请参见
9.1
的注释):


人脸ID可从iOS 11获得,默认情况下,iPhone X随iOS 11提供。在LocalAuth框架中,他们添加了一个“biometryType”属性,可以让您检测设备上是否有可用的面部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
}

因为我非常喜欢扩展。我对这个答案的措辞有点不同。本质是一样的。这是一个临时分机

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
这是我的“助手类”,它还包括密码

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

来自@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
    }
}

}

我为本地身份验证创建了一个单例类,因为它有助于使用整个应用程序的
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 authType {
        case .none:
            print("Device not registered with TouchID/FaceID")
        case .touchID:
            print("Device support TouchID")
        case .faceID:
            print("Device support FaceID")
        }
 }

更新swift 5,开关流需要默认条件

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
    }

}
测试用例如下所示

// need to import LocalAuthentication in the calling file
// import LocalAuthentication
let currentType = LAContext().biometricType
print("biometry type > \(currentType)")
// biometry type > touchID
如果你想在模拟器中测试,你需要注册touchId/faceId
模拟器>硬件>触摸ID/面部ID>注册。

请参考为“使用Face ID或Touch ID将用户登录到您的应用程序”提供的苹果示例代码,这将有助于轻松理解身份验证

苹果示例代码链接-

请阅读下面链接中示例代码的详细说明。

开始在12 Pro上测试一些新应用程序,并意识到我发布的应用程序只有触摸ID而没有面部ID

我来到这里,看到了所有这些,所以我开始尝试更改我的触摸ID代码,但我需要做的只是将隐私密钥添加到info.plist

信息属性列表➕

然后向下滚动至:隐私-面部ID使用说明,(类型:字符串),(值:是)


太容易了在刚刚发布的Xcode 9.2 beta版中,iOS 11.2版中,
LABiometryType
enum值已更改为
faceID
touchID
@tfrank377感谢您的提醒。我已经更新了答案。我们是否可以仅使用模拟器检测设备是否支持面部ID或触摸ID?是的,您可以使用模拟器进行测试。选择Simulator->Hardware->Touch ID->Cases这将基于Simulator为两者提供支持。您尚未回答问题。问题不在于它是什么?但是如何/>谢谢你。正是我要找的:)biometryType的文档说明:“只有当CaneValuePolicy成功用于生物识别策略时,才会设置此属性”。因此,如果CaneValuationPolicy失败(例如touchid/faceid完全或每个应用程序都被停用)
biometricType()
返回
。无
。所以
biometricType()
不检查硬件的可用性,但检查应用程序是否可以访问硬件。@ValeriyVan您找到检查设备上硬件可用性的方法了吗?似乎每个人都在给出biometricType作为答案,但是,正如您所说,如果您只是试图向用户提供一个显示“面部ID”或“触摸ID”的按钮,以便用户在设备尚无法通过生物识别验证时授权其中一个,那么这实际上是错误的答案。@SAHM,实际上,我没有找到比检查设备类型更好的方法。这是不好的方式,因为它不是未来的证明。希望苹果会更新API来解决这个问题。这很有趣,因为他们实际上说“不要在支持Face ID的设备上引用Touch ID。相反,不要在支持Touch ID的设备上引用Face ID。检查设备的功能并使用适当的术语。有关开发人员指导,请参阅LABiometryType。”但是,除非用户已经授权,否则无法做到这一点。我们能否仅使用模拟器来检测设备是否支持面部ID或触摸ID?@shaqirsaiyed-Yes。我们可以检测设备是否支持面部ID或触摸ID。当你在iPoFX或以后的设备上运行应用程序时,它会自动检测iPhone 8或iPhone 8PUS设备的脸ID。如果没有任何物理设备,并在模拟器中运行,它将检测Touch ID.consider。那个么我能检测到吗?我们能只用模拟器检测设备是否支持面部ID或触摸ID吗?你们能帮我解决这个问题吗
-(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;

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

}
// need to import LocalAuthentication in the calling file
// import LocalAuthentication
let currentType = LAContext().biometricType
print("biometry type > \(currentType)")
// biometry type > touchID