Flutter -打开应用程序时提示输入TouchID/FaceID

mfuanj7w  于 2022-12-05  发布在  Flutter
关注(0)|答案(4)|浏览(150)

我在实现TouchID/FaceID身份验证时遇到问题,无法在用户打开应用程序时自动提示用户。我正在为TouchID/FaceID使用local_auth依赖项。
在下面的代码中,生物认证会在应用恢复时弹出,但也不能解除,如果你按下home键,它会解除TouchID提示但立即开始重试,如果你一直这样尝试会造成死循环,它还会随机提示两次,所以即使你用第一次TouchID提示成功登录,我在登录页面上也有一个TouchID按钮,用户可以按下它来手动提示TouchID,但我很想重现我的银行应用程序和其他应用程序的工作方式,当你自动打开应用程序时,TouchID会提示。

void initState() {
  super.initState();

  SystemChannels.lifecycle.setMessageHandler((msg) async {
    if (msg==AppLifecycleState.resumed.toString()) {
      // If can pop, app is not at login screen
      // so don't prompt for authentication
      if (!Navigator.canPop(context)) {
        if (_useFingerprint) {
          SharedPreferences prefs = await SharedPreferences.getInstance();
          String password = prefs.getString('password');
          biometricAuthentication(_username, password);
        }
     }
  }
});

void biometricAuthentication(String user, String pass) async {
  print("Biometric Authentication Called");
  bool didAuthenticate = false;
  try {
    didAuthenticate = await localAuth.authenticateWithBiometrics(localizedReason: 'Please authenticate');
  } on PlatformException catch (e) {
    print(e);
  }

  if (!mounted) {
    return;
  } 

  if (!didAuthenticate) {
    return;
  }
  else {
    normalLogin(user, pass);   
  }
}
yhqotfr8

yhqotfr81#

这对我很有效

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (await _isBiometricAvailable()) {
    await _getListOfBiometricTypes();
    await _authenticateUser();
  }

  runApp(App());
}
gcmastyq

gcmastyq2#

我想我已经解决了。如果还有其他问题,请告诉我。

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  bool isAuthenticated = await Authentication.authenticateWithBiometrics();

  if (isAuthenticated) {
   runApp(MyApp());
 } else {
   main();
 }
}

这似乎在每次打开应用程序时都有效。

class Authentication {
  static Future<bool> authenticateWithBiometrics() async {
   final LocalAuthentication localAuthentication = LocalAuthentication();
   bool isBiometricSupported = await localAuthentication.isDeviceSupported();
   bool canCheckBiometrics = await localAuthentication.canCheckBiometrics;

   bool isAuthenticated = false;

   if (isBiometricSupported && canCheckBiometrics) {
     isAuthenticated = await localAuthentication.authenticate(
       localizedReason: 'Please complete the biometrics to proceed.',
       //biometricOnly: true,
       stickyAuth: true,
     );
   }

   return isAuthenticated;
 }
}
lrl1mhuk

lrl1mhuk3#

试试这个:
创建一个类来处理应用的生命周期

class LifecycleEventHandler extends WidgetsBindingObserver {
      final Function onResume;
    
      LifecycleEventHandler(this.onResume);
    
      @override
      Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
        switch (state) {
          case AppLifecycleState.resumed:
            onResume.call();
            break;
          default:
            break;
        }
      }
    }

然后在你的主:

@override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(
      LifecycleEventHandler(() async {
        //Put your auth function here (biometric auth or passcode)
      }),
    );
  }

每次返回到应用程序时,都会执行您放置的操作

vlju58qv

vlju58qv4#

**免责声明:**我在iOS开发方面没有太多经验,所以我在这里从Android中推断。

我认为问题是系统对话框使您的应用程序处于非活动状态,从而导致
1.应用程序恢复
1.应用程序显示TouchID/FaceID对话框,从而使其自身处于非活动状态
1.用户确认对话
1.您的应用程序再次进入前台,从而 * 恢复 *
1.请参阅步骤1

可能的解决方案

  • 不要在应用程序启动时要求验证,而是在应用程序中将要发生重要操作时要求验证。这是验证功能的预期使用方式,因此它是最常用的解决方案。(我的最爱)
  • 设置一个时间限制,比如只在用户离开超过x秒时才显示对话框,从而从短的非活动阶段中过滤掉长的非活动阶段(包括用于身份验证的阶段)。(我觉得这是一个变通办法)

相关问题