local_auth를 사용하여 flutter에 생체인증 로그인을 구현해보자.
local auth 의 Installing을 참고하여 설치를 진행한다.
혹은 아래의 명령어를 Terminal에 입력하여 설치를 진행한다. Terminal 위치는 프로젝트 내여야 한다.
flutter pub add local_auth
이제 import 'package:local_auth/local_auth.dart';
를 import하여 local auth 패키지에 접근할 수 있다.
Info.plist에 지문과 페이스 ID를 위해 아래를 추가한다.
<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>
이 패키지는 SDK 16 이상에서 동작한다. isDeviceSupported() 함수는 SDK 23 이하에서는 항상 false를 리턴하니 주의!
AndroidManifest.xml의 MainActivity를 FlutterFragmentActivity로 수정해준다.
<!--from this-->
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"/>
<!--to this-->
<activity
android:name="io.flutter.embedding.android.FlutterFragmentActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"/>
또한, 권한도 추가한다.
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
android/app/src/main/java/[패키지 루트] 혹은 android/app/src/main/kotlin/[패키지 루트]에 있는 MainActivity를 종류에 따라 아래와 같이 수정한다.
java를 사용하는 경우 아래와 같이 수정한다.
/// MainActivity.java
/// from this
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
}
/// MainActivity.java
/// to this
import io.flutter.embedding.android.FlutterFragmentActivity;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterFragmentActivity {
// ...
}
kotlin를 사용하는 경우 아래와 같이 수정한다.
///MainActivity.kt
/// from this
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
// ...
}
///MainActivity.kt
/// to this
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity() {
// ...
}
import 'package:flutter/services.dart';
import 'package:local_auth/local_auth.dart';
import 'package:local_auth/error_codes.dart' as auth_error;
import 'package:local_auth_android/local_auth_android.dart';// for AndroidAuthMessages
import 'package:local_auth_ios/local_auth_ios.dart';// for IOSAuthMessages
enum _SupportState { unknown, supported, unsupported }
class LocalAuthApi {
static final _auth = LocalAuthentication();
static Future<bool> hasBiometrics() async {
try {
//하드웨어 지원이 가능한지 여부만 표시되며 장치에 생체 인식이 등록되어 있는지 여부는 표시되지 않음
return await _auth.canCheckBiometrics ?? false;
} on PlatformException catch (e) {
Util.print(e);
}
return false;
}
static Future<List<BiometricType>> getBiometrics() async {
try {
//등록된 생체인식 목록을 얻기
return await _auth.getAvailableBiometrics();
} on PlatformException catch (e) {
Util.print(e);
}
return <BiometricType>[];
}
static Future<bool> authenticate() async {
final isAvailable = await hasBiometrics();
if (!isAvailable) return false;
try {
// 가능한 경우 생체 인식 인증을 사용하지만 핀, 패턴 또는 비밀번호로 대체할 수도 있음
return await _auth.authenticate(
localizedReason: '생체정보를 인식해주세요.',
options: const AuthenticationOptions(
biometricOnly: true,
useErrorDialogs: true, //기본 대화 상자를 사용하기
stickyAuth: true,//false : 앱 재실행 되었을때 플러그인 인증을 재시도
),
authMessages: [
IOSAuthMessages(
lockOut: '생체인식 활성화',
goToSettingsButton: '설정',
goToSettingsDescription: '기기 설정으로 이동하여 생체 인식을 등록하세요.',
cancelButton: '취소',
localizedFallbackTitle: '다른 방법으로 인증',
),
AndroidAuthMessages(
biometricHint: '생체 정보를 스캔하세요.',
biometricNotRecognized: '생체정보가 일치하지 않습니다.',
biometricRequiredTitle: '생체',
biometricSuccess: '로그인',
cancelButton: '취소',
deviceCredentialsRequiredTitle: '생체인식이 필요합니다.',
deviceCredentialsSetupDescription: '기기 설정으로 이동하여 생체 인식을 등록하세요.',
goToSettingsButton: '설정',
goToSettingsDescription: '기기 설정으로 이동하여 생체 인식을 등록하세요.',
signInTitle: '계속하려면 생체 인식을 스캔',
)
]
);
} on PlatformException catch (e) {
Util.print(e);
}
return false;
}
}
이 장치에서 로컬 인증이 가능한지 확인하려면 이 함수를 호출한다. 이 함수는 하드웨어 지원의 유무만을 나타내며 장치에 등록된 생체 인식 정보가 있는지 여부는 확인하지 않는다.
등록된 생체 인식 목록을 얻으려면 이 함수를 호출한다.
가능한 경우 생체 인식을 사용하지만 핀, 패턴 또는 패스코드로의 대체도 허용한다.
AuthMessages의 한 종류인 IOSAuthMessages는 IOS를 위한 커스텀 메세지를 지원한다.
import 'package:local_auth_ios/local_auth_ios.dart';
를 import하여 사용한다.
AuthMessages의 한 종류인 AndroidAuthMessages는 Android를 위한 커스텀 메세지를 지원한다.
import 'package:local_auth_android/local_auth_android.dart';
를 import하여 사용한다.