Notice
Recent Posts
Recent Comments
Link
투케이2K
130. (ios/swift) Touch ID , Face ID 생체 간편 인증 수행 실시 - 얼굴 인식 , 지문 인식 본문
[개발 환경 설정]
개발 툴 : XCODE
개발 언어 : SWIFT
[사전 설정 필요]
[ViewController]
import UIKit
class ViewController: UIViewController {
// MARK: [뷰 메모리 로드 수행 실시]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("")
print("===============================")
print("[ViewController >> viewDidLoad() :: 뷰 메모리 로드 실시]")
print("===============================")
print("")
// [앱 딜리게이트 노티피케이션 알림 확인 등록]
NotificationCenter.default.addObserver(
self, // 뷰 지정
selector: #selector(simpleAuthNotification(_:)), // userInfo 데이터 있는 경우 : @objc func appDelegateCall(_ notification:NSNotification) {}
name: NSNotification.Name("simpleAuthNotification"), // 알림 식별자
object: nil // 객체
)
}
// MARK: - [뷰 종료 상태]
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
print("")
print("===============================")
print("[ViewController >> viewDidDisappear() :: 뷰 종료 상태]")
print("===============================")
print("")
// [앱 딜리게이트 노티피케이션 알림 확인 해제]
NotificationCenter.default.removeObserver(
self, // 뷰 지정
name: NSNotification.Name("simpleAuthNotification"), // 알림 해제
object: nil
)
}
// MARK: - [버튼 클릭 이벤트 정의 실시]
@IBAction func buttonAction(_ sender: Any) {
// [생체 인증 수행 실시]
self.simpleAuth()
}
// MARK: - [생체 인증 수행 실시]
func simpleAuth(){
print("")
print("===============================")
print("[ViewController >> simpleAuth() : 생체 인증 수행 실시]")
print("===============================")
print("")
DispatchQueue.main.async {
// [생체 인증 클래스 객체 생성 실시]
let a_auth = A_Auth()
// [생체 인증 수행 실시]
if #available(iOS 11.0, *) { // MARK: [특정 ios 버전 이상 사용 가능]
// MARK: [생체 인증 사용 가능 여부 확인]
let canEvaluateDic : Dictionary<String, Any> = a_auth.canEvaluate()
print("")
print("===============================")
print("[ViewController >> simpleAuth() :: 생체 인증 사용 여부 확인]")
print("결과 :: Face ID / Touch ID 사용 가능 여부 확인")
print("canEvaluateDic :: \(canEvaluateDic)")
print("===============================")
print("")
if (canEvaluateDic["result"] != nil) == true { // [생체 인증 사용 가능한 경우]
// MARK: [생체 인증 수행 실시]
a_auth.evaluate()
}
else { // [생체 인증 사용 불가능한 경우]
// [팝업창 알림 표시 수행 실시]
self.showAlert(
tittle: "생체 사용 가능 여부",
content: "\(canEvaluateDic["msg"]!)",
okBtb: "확인",
noBtn: "취소"
)
}
} else {
print("")
print("===============================")
print("[ViewController >> simpleAuth() :: 생체 인증 사용 여부 확인]")
print("결과 :: IOS 버전 11 미만 >> 생체 인증 사용 제한 디바이스")
print("===============================")
print("")
}
}
}
// MARK: - [생체 인증 수행 결과 메시지 확인 실시]
@objc func simpleAuthNotification(_ notification:NSNotification) {
print("")
print("===============================")
print("[ViewController >> simpleAuthNotification() :: 생체 인증 노티피케이션 수신 확인]")
print("message :: \(notification.userInfo!["message"]!)")
print("===============================")
print("")
// [팝업창 알림 표시 수행 실시]
self.showAlert(
tittle: "생체 인증 결과",
content: "\(notification.userInfo!["message"]!)",
okBtb: "확인",
noBtn: "취소"
)
}
// MARK: [alert 팝업창 호출 메소드 정의 실시 : 이벤트 호출 시]
// 호출 방법 : showAlert(tittle: "title", content: "content", okBtb: "확인", noBtn: "취소")
func showAlert(tittle:String, content:String, okBtb:String, noBtn:String) {
DispatchQueue.main.async {
// [UIAlertController 객체 정의 실시]
let alert = UIAlertController(title: tittle, message: content, preferredStyle: UIAlertController.Style.alert)
// [인풋으로 들어온 확인 버튼이 nil 아닌 경우]
if(okBtb != "" && okBtb.count>0){
let okAction = UIAlertAction(title: okBtb, style: .default) { (action) in
// [확인 버튼 클릭 이벤트 내용 정의 실시]
return
}
alert.addAction(okAction) // 버튼 클릭 이벤트 객체 연결
}
// [인풋으로 들어온 취소 버튼이 nil 아닌 경우]
if(noBtn != "" && noBtn.count>0){
let noAction = UIAlertAction(title: noBtn, style: .default) { (action) in
// [취소 버튼 클릭 이벤트 내용 정의 실시]
return
}
alert.addAction(noAction) // 버튼 클릭 이벤트 객체 연결
}
// [alert 팝업창 활성 실시]
self.present(alert, animated: false, completion: nil)
}
}
} // [클래스 종료]
[A_Auth]
import UIKit
// MARK: [import 추가 실시]
import LocalAuthentication
class A_Auth {
// MARK: [클래스 설명]
/*
1. A_Auth : 생체 인증 수행 액티비티
2. info.plist 권한 등록 필요 :
- Privacy - Face ID Usage Description
3. import 추가 필요 :
- import LocalAuthentication
*/
// MARK: - [전역 변수 선언 실시]
private let context = LAContext() // [생체 인증 객체]
private let policy: LAPolicy // [deviceOwnerAuthenticationWithBiometrics 객체]
private let localizedReason: String // [생체 인증 팝업창 내용]
private var error: NSError? // [에러 발생 타입]
static let POPUP_CONTENT = "생체 인증을 수행합니다." // [생체 인증 팝업창 내용]
static let POPUP_FALLBACK = "" // [생체 인증 팝업창 버튼 내용]
static let POPUP_CANCLE = "취소" // [생체 인증 팝업창 버튼 내용]
static let ERROR_CHECK_FAIL = "ERROR CHECK FAIL" // [에러 체크 실패 멘트 저장]
static let CHECK_SUCCESS = "SUCCESS" // [생체 인증 사용 여부 및 생체 인증 결과 성공 멘트 저장]
// MARK: - [클래스 생성자 초기화 실시 : 생체 인증 팝업창 내용 표시 설정]
init(policy: LAPolicy = .deviceOwnerAuthenticationWithBiometrics,
localizedReason: String = A_Auth.POPUP_CONTENT,
localizedFallbackTitle: String = A_Auth.POPUP_FALLBACK,
localizedCancelTitle: String = A_Auth.POPUP_CANCLE) {
// [전역 변수에 매핑 실시]
self.policy = policy
self.localizedReason = localizedReason
self.context.localizedFallbackTitle = localizedFallbackTitle
self.context.localizedCancelTitle = localizedCancelTitle
}
// MARK: - [생체 인증 타입 정의]
enum BiometricType {
case none
case touchID
case faceID
case unknown
}
@available(iOS 11.0, *) // [특정 IOS 버전 이상 사용 가능]
private func biometricType(for type: LABiometryType) -> BiometricType {
switch type {
case .none:
return .none
case .touchID:
return .touchID
case .faceID:
return .faceID
@unknown default:
return .unknown
}
}
// MARK: - [생체 인증 에러 메시지 리턴 수행 부분]
@available(iOS 11.0, *) // [특정 IOS 버전 이상 사용 가능]
private func biometricError(from nsError: NSError) -> (Int, String) {
var retry = 0 // 재실행 여부
var error = "" // 에러 메시지
switch nsError {
// MARK: [생체 인증에 실패하였습니다. 재실행하시겠습니까?]
case LAError.authenticationFailed:
retry = 1
error = "생체 인증에 실패하였습니다. 재실행하시겠습니까?"
// MARK: [생체 인증 동작을 취소하였습니다. 재실행하시겠습니까?]
case LAError.userCancel:
retry = 1
error = "생체 인증 동작을 취소하였습니다. 재실행하시겠습니까?"
// MARK: [생체 인증 기능이 필요합니다. 재실행하시겠습니까?]
case LAError.userFallback:
retry = 1
error = "생체 인증 기능이 필요합니다. 재실행하시겠습니까?"
// MARK: [기기에서 생체 인식을 사용할 수 없습니다. 권한을 거부하신 경우 확인해주세요.]
case LAError.biometryNotAvailable:
retry = 0
error = "기기에서 생체 인식을 사용할 수 없습니다. 권한을 거부하신 경우 확인해주세요."
// MARK: [등록된 생체 인식 ID가 없습니다. 생체 인증 등록 후 사용해 주세요.]
case LAError.biometryNotEnrolled:
retry = 0
error = "등록된 생체 인식 ID가 없습니다. 생체 인증 등록 후 사용해 주세요."
// MARK: [생체 인증 사용 잠금 (LOCK) 상태입니다. 디바이스에 등록된 생체 인증을 확인 후 다시 실행해주세요.]
case LAError.biometryLockout:
retry = 0
error = "생체 인증 사용 잠금 (LOCK) 상태입니다. 디바이스에 등록된 생체 인증을 확인 후 다시 실행해주세요."
// MARK: [생체 인증 기능 동작이 취소되었습니다. 잠시후 다시 실행해주세요.]
case LAError.appCancel:
retry = 0
error = "생체 인증 기능 동작이 취소되었습니다. 잠시후 다시 실행해주세요."
// MARK: [생체 인증에서 일시적인 문제가 발생하였습니다.]
default:
retry = 0
error = "생체 인증에서 일시적인 문제가 발생하였습니다."
}
/*
print("")
print("===============================")
print("[A_Auth >> biometricError() :: 생체 인증 에러 메시지 반환 실시]")
print("error :: ", error)
print("===============================")
print("")
// */
return (retry, error)
}
// MARK: - [생체 인증 수행 >> 사용 가능 여부 판단]
@available(iOS 11.0, *) // [특정 IOS 버전 이상 사용 가능]
func canEvaluate() -> Dictionary<String, Any> {
print("")
print("===============================")
print("[A_Auth >> canEvaluate() :: 생체 인증 [사용] 가능 여부 [판단] 실시]")
print("===============================")
print("")
// [세마포어 선언 : 프로그램 로직을 동기화 구현]
let semaphore = DispatchSemaphore(value: 0) // [value 0 값은 대기 상태 선언]
var returnDic : Dictionary<String, Any> = [String : Any]() // 리턴 딕셔너리
var errorData : NSError? = nil // 에러 타입
var errorMsg = "" // 에러 메시지
guard self.context.canEvaluatePolicy(self.policy, error: &self.error) else {
// [생체 인증 타입 매핑]
let type = self.biometricType(for: self.context.biometryType)
// [에러 체크 문제 발생]
guard let error = self.error
else {
print("")
print("===============================")
print("[A_Auth >> canEvaluate() :: 생체 인증 [사용] 가능 [결과] 확인]")
print("결과 :: 에러 체크 실패")
print("type :: ", type)
print("error :: ", error?.localizedDescription ?? "")
print("===============================")
print("")
// [생체 인증 사용 가능 여부 에러 결과 반환]
returnDic["result"] = false
returnDic["msg"] = A_Auth.ERROR_CHECK_FAIL
// [세마포어 신호 알림]
semaphore.signal()
// [리턴 데이터 반환]
return returnDic
}
// [에러 타입 삽입 실시]
errorData = error as NSError
print("")
print("===============================")
print("[A_Auth >> canEvaluate() :: 생체 인증 [사용] 가능 [결과] 확인]")
print("결과 :: 사용 불가능")
print("type :: ", type)
print("retry :: ", self.biometricError(from: errorData as! NSError).0)
print("msg :: ", self.biometricError(from: errorData as! NSError).1)
print("===============================")
print("")
// [에러 메시지 삽입]
errorMsg = self.biometricError(from: errorData!).1 // [에러 메시지]
// [에러 발생 데이터 생성 실시]
returnDic["result"] = false
returnDic["msg"] = errorMsg
// [세마포어 신호 알림]
semaphore.signal()
// [리턴 데이터 반환]
return returnDic
}
print("")
print("===============================")
print("[A_Auth >> canEvaluate() :: 생체 인증 [사용] 가능 [결과] 확인]")
print("결과 :: 사용 가능")
print("type :: ", biometricType(for: context.biometryType))
print("msg :: ", A_Auth.CHECK_SUCCESS)
print("===============================")
print("")
// MARK: [evaluate 사용 가능]
returnDic["result"] = true
returnDic["msg"] = A_Auth.CHECK_SUCCESS
// [세마포어 신호 알림]
semaphore.signal()
// [세마포어 확인 대기]
semaphore.wait()
// [리턴 데이터 반환]
return returnDic
}
// MARK: - [생체 인증 수행 >> 결과 확인 실시]
@available(iOS 11.0, *) // [특정 IOS 버전 이상 사용 가능]
func evaluate() {
print("")
print("===============================")
print("[A_Auth >> evaluate() :: 생체 인증 [수행] 실시]")
print("===============================")
print("")
self.context.evaluatePolicy(self.policy, localizedReason: self.localizedReason) { (success, error) in
if success == true {
print("")
print("===============================")
print("[A_Auth >> evaluate() :: 생체 인증 [결과] 확인 실시]")
print("결과 :: 생체 인증 성공")
print("msg :: ", A_Auth.CHECK_SUCCESS)
print("===============================")
print("")
// [노티피케이션 알림 전송 실시]
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: "simpleAuthNotification"), // 알림을 식별하는 태그
object: nil, // 발송자가 옵저버에게 보내려고 하는 객체
userInfo: ["message" : "\(A_Auth.CHECK_SUCCESS)"] // 객체의 저장소 [AnyHashable: Any] 형태
)
return
}
else {
print("")
print("===============================")
print("[A_Auth >> evaluate() :: 생체 인증 [결과] 확인 실시]")
print("결과 :: 에러 발생 확인")
print("error :: ", error?.localizedDescription ?? "")
print("retry :: ", self.biometricError(from: error as! NSError).0)
print("msg :: ", self.biometricError(from: error as! NSError).1)
print("===============================")
print("")
// MARK: [재실행 수행인 경우]
if self.biometricError(from: error as! NSError).0 == 1 {
// [다시 호출 수행 실시]
self.evaluate()
}
else {
// [노티피케이션 알림 전송 실시]
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: "simpleAuthNotification"), // 알림을 식별하는 태그
object: nil, // 발송자가 옵저버에게 보내려고 하는 객체
userInfo: ["message" : self.biometricError(from: error as! NSError).1 ?? ""] // 객체의 저장소 [AnyHashable: Any] 형태
)
}
return
}
}
}
} // [클래스 종료]
[결과 출력]
반응형
'IOS' 카테고리의 다른 글
Comments