iOS

터치 아이디 및 로컬 인증(LocalAuthentication) 프레임워크

jangsilverbaby 2021. 12. 16. 12:34

1. 로컬 인증 프레임워크 반입 구문을 작성한다.

 

import LocalAuthentication

 

2. 인증에 관한 종합 정보를 관리하는 객체인 인증 컨텍스트를 정의한다. 필요할 때마다 매번 객체 인스턴스를 생성해서 사용한다.

 

let context = LAContext()

 

3. 터치 아이디 인증창을 구성한다. 오류 코드를 처리할 변수와 터치 아이디 인증창에 들어갈 메세지를 정의한다. 오류가 없을 수도 있으니 타입은 옵셔널로 한다.

 

let context = LAContext()

var error: NSErrror?
let msg = "로그인을 위해 인증이 필요합니다."

 

4. canEvaluatePolicy 메소드를 호출하여 터치 아이디 인증을 사용할 수 있는 지 프레임워크에 문의한다. 이 메소드는 평가할 정책과 오류 객체에 대한 두 개의 인자값을 사용한다.

 

// ..(중략)..
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {

}

 

.deviceOwnerAuthenticationWithBiometrics는 LAPolicy라는 열거형 객체의 속성이다. 다음과 같은 다중 조건이 모두 만족되는 지 여부를 체크하는 인자값이다.

- 해당 기기가 터치 아이디 인증을 지원하는가?

- 해당 기기 설정에서 터치 아이디가 허용되어 있는가?

- 패스 코드가 설정되어 있는가?

- 최소한 하나 이상의 지문이 등록되어 있는가?

이 조건 중 하나라도 만족하지 못한다면 결과는 false로 반환된다.

false로 반환되면 두 번째 인자값으로 전달된 참조 형태의 오류 객체를 통해 오류 코드가 전달되므로 이를 분석하여 오류의 원인을 확인하고, 그에 맞는 처리를 해야한다.

true로 반환되면 이들 인증 정책을 모두 적용할 수 있다는 뜻이므로 터치 아이디 실제로 인증창을 실행한다.

 

5. evaluatePolicy 메소드를 사용하여 인증창을 실행한다.

 

// ..(중략)..
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: msg, reply: {(success, e) in
    
    })
}

 

첫 번째 인자값 : 인증 정책 조건

두 번째 인자값 : 인증창에 표시될 인증 사유 메세지

세 번째 인자값 : 완료 처리 클로저, 성공 여부에 대한 Bool 타입의 인자값과 오류 원인이 기록될 NSError타입의 인자값이 함께 전달된다. 실질적으로 인증 후의 처리 로직은 모두 완료 클로저에 구현된다.

 

6. 클로저 내부의 로직은 인자값을 이용하여 다음과 같이 구현되는 경우가 대부분이다.

 

//..(중략)..
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: msg, reply: {(success, e) in
    // 인증 과정을 진행한다.
    if success { // 인증 성공에 대한 로직
    	// 키 체인 등에 저장된 인증값을 이용하여 안심하고 인증 진행
    } else { // 실패에 대한 로직
        print(e!.localizedDescription)
        // switch 구문을 통해 오류 코드별로 원인을 분석하고 이에 맞추어 대응
        switch (e!._code) {
            case LAError.systemCancel.rawValue:
            print("시스템에 의해 인증이 최소되었습니다.")
            case LAError.userCancel.rawValue:
            print("사용자에 의해 인증이 최소되었습니다.")        
            case LAError.userFallback.rawValue:
            print("사용자가 별도의 로그인 창을 통한 인증을 선택하였습니다.")
            OperationQueue.main.addOperation () { ... }
            defalut:
            print("Authentication failed")
            OperationQueue.main.addOperation () { ... }
        }
    }
})

 

_code 속성의 값은 정수형이기 떄문에, LAError 객체의 속성을 rawValue를 사용하여 정수형으로 값을 변환한 다음에 비교해야한다. 또한 클로저는 서브 스레드에서 수행되므로, 로그인 화면을 띄워주는 등 UI 변경이 필요한 오류 처리의 경우 OperationQueue.main 블록이나 DispatchQueue.main 블록을 사용하여 메인 스레드에서 실행될 수 있도록 처리해야 한다.

 

7. context.canEvaluatePolicy() 조건을 통과하지 못한 오류들은 if context.canEvaluatePolicy() 조건절의 else 블록을 이용하여 처리한다. (터치 아이디를 지원하지 않는 기기이거나 지원하더라도 지문이 등록되어 있지 않은 경우) 이때에는 오류가 무엇이든 간에 사용자가 아이디와 패스워드를 입력할 수 있도록 화면을 전환하는 것이 적절하다.

 

// ..(중략)..
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
    context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: msg, reply: {(success, e) in
    // ..(중략)..
    })
} else {
    print(error!.localizedDescription)
    switch (error!.code) {
        case LAError.biometryNotEnrolled.rawValue:
        print("터치 아이디가 등록되어 있지 않습니다.")
        case LAError.passcodeNotSet.rawValue:
        print("패스 코드가 설정되어 있지 않습니다.")
        default: // LAError.touchIDNotAvailable 포함
        print("터치 아이디를 사용할 수 없습니다.")
    }
}

 

 

참고 : 재은씨의 꼼꼼한 Swift 실전편