В настоящее время я реализую TouchID с использованием LocalAuthentication
framework.
Моя первоначальная попытка службы выглядит следующим образом:
import Foundation
import LocalAuthentication
public enum AuthenticationState {
case unknown
case authenticated
case unauthenticated
public func isAuthenticated() -> Bool {
return self == .authenticated
}
}
public protocol TouchIDServiceType {
var authState: AuthenticationState { get }
func authenticate(reason: String, completion: @escaping (AuthenticationState) -> Void) -> Void
func removeAuthentication() -> Void
}
public protocol LAContextType: class {
func canEvaluatePolicy(_ policy: LAPolicy, error: NSErrorPointer) -> Bool
func evaluatePolicy(_ policy: LAPolicy, localizedReason: String, reply: @escaping (Bool, Error?) -> Void)
}
public class TouchIDService: TouchIDServiceType {
public var authState: AuthenticationState = .unknown
private var context: LAContextType
private var policy = LAPolicy.deviceOwnerAuthentication
public init(context: LAContextType = LAContext()) {
self.context = context
}
public func authenticate(reason: String, completion: @escaping (AuthenticationState) -> Void) -> Void {
var error: NSError?
if context.canEvaluatePolicy(policy, error: &error) {
context.evaluatePolicy(policy, localizedReason: reason) { (success, error) in
DispatchQueue.main.async {
if success {
self.authState = .authenticated
completion(.authenticated)
} else {
self.authState = .unauthenticated
completion(.unauthenticated)
}
}
}
} else {
authState = .authenticated
completion(.authenticated)
}
}
public func removeAuthentication() -> Void {
authState = .unknown
context = LAContext() // reset the context
}
}
extension LAContext: LAContextType { }
Внутри моего AppDelegate
У меня есть простая функцияэто возвращает логическое значение, я использую это, чтобы решить, какое действие предпринять, если пользователь аутентифицирован или нет.
private func authenticate(completion: @escaping (Bool) -> Void) {
localAuthenticator.authenticate(reason: "Authentication is required") { state in
completion(state == .authenticated)
}
}
Что-то вроде:
@discardableResult
private func performLocalAuth() -> Bool {
if IdentityProvider.shared.alreadyLoggedIn() {
authenticate { [weak self] success in
if !success { IdentityProvider.shared.logout() }
}
return true
} else {
return false
}
}
У меня есть требование, что еслипользователь отменяет вызов, нажав кнопку «Домой», я не должен рассматривать это как неудачную попытку, а вместо этого, когда дом возвращается на передний план, снова вызвать его с помощью аутентификатора TouchID.
Только если пользователь нажимает или отменяетили если задача не пройдена, я должен их правильно отключить.
В этом случае пользователь случайно открывает приложение, а не выходит из системы, а просто закрывает его.
IЯ не уверен, как и где я должен проверять, была ли нажата кнопка «Домой» и возможно ли это.