Autenticação biométrica no aplicativo Flutter

Tempo de leitura: 5 minutes

Olá pessoal! hoje estou escrevendo um blog sobre segurança ou podemos dizer privacidade. Neste blog, aprendemos como adicionar autenticação de impressão digital ao nosso aplicativo flutter de uma maneira muito fácil. Como desenvolvedor, acho que a biometria é muito segura. Neste blog, aprendemos como implementar a Autenticação Biométrica no aplicativo Flutter.

Para Autenticação Biométrica, precisamos de nosso banco de dados local pelo qual podemos verificar a impressão digital.

Usamos muitos tipos de biometria:

  • BiometricType.face
  • BiometricType.fingerprint
  • BiometricType.weak
  • BiometricType.strong

 

Implementação:

Primeiro, temos que criar um novo For BioMetric Authentication primeiro precisamos adicionar dependências em pubspec.ymal que é local_auth.

dependencies:
  local_auth: ^2.1.6

> local_auth: Este plug-in do Flutter fornece os meios para executar a autenticação local no dispositivo do usuário. Importe o seguinte arquivo para sua classe StatefulWidget.

import 'package:local_auth/local_auth.dart';

Em dispositivos compatíveis, isso inclui autenticação com biometria, como impressão digital ou reconhecimento facial. Ele suporta Android, IOS e Windows. Para local_auth, temos que verificar os recursos do dispositivo.

>Device capabilities: Se quisermos usar a Autenticação de impressão digital, então temos que verificar a capacidade do nosso dispositivo para verificar a capacidade, devemos chamar canCheckBiometrics() ou isDeviceSupport()

import 'package:local_auth/local_auth.dart';
final LocalAuthentication auth = LocalAuthentication();
final bool canAuthenticateWithBiometrics = await auth.canCheckBiometrics;
final bool canAuthenticate = canAuthenticateWithBiometrics || await auth.isDeviceSupported();

canCheckBiometric() designa apenas se o suporte de hardware está disponível, não se o dispositivo possui alguma biometria registrada. Para obter uma lista de biometria registrada, chame getAvailableBiometrics().

Este plug-in será criado e executado no SDK 16+, mas isDeviceSupported() sempre retornará false antes do SDK 23.

Dialogs:

O plug-in fornece caixas de diálogo padrão para os seguintes casos:

  1. Passcode/PIN/Pattern Not Set:  o usuário ainda não configurou uma senha no iOS ou um PIN/padrão no Android.
  2. Bio-metrics Not Enrolled: o usuário não se inscreveu em nenhuma biometria no dispositivo.
import 'package:local_auth/error_codes.dart' as auth_error;
    try {
      final bool didAuthenticate = await auth.authenticate(
          localizedReason: 'Please authenticate to show account balance',
          options: const AuthenticationOptions(useErrorDialogs: false));
    } on PlatformException catch (e) {
      if (e.code == auth_error.notAvailable) {
        // Add handling of no hardware here.
      } else if (e.code == auth_error.notEnrolled) {
      } else {}
    }

Se você deseja editar o diálogo, pode passar AuthMessages para cada plataforma na qual deseja editar a mensagem.

import 'package:local_auth_android/local_auth_android.dart';
import 'package:local_auth_ios/local_auth_ios.dart';
    final bool didAuthenticate = await auth.authenticate(
        localizedReason: 'Please authenticate to show account balance',
        authMessages: const <AuthMessages>[
          AndroidAuthMessages(
            signInTitle: 'Oops! Biometric authentication required!',
            cancelButton: 'No thanks',
          ),
          IOSAuthMessages(
            cancelButton: 'No thanks',
          ),
        ]);

 

>IOS Integration:

Você precisa adicionar essas linhas em Info. arquivo plist. Não fazer isso resulta em uma caixa de diálogo informando ao usuário que seu aplicativo não foi atualizado para usar o Face ID.

<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>

>Integração Android:

  • Se você estiver usando FlutterActivity diretamente, altere-o para FlutterFragmentActivity em seu AndroidManifest.xml.
  • Se você estiver usando uma atividade personalizada, atualize seu MainActivity.java

ou MainActivity.

import io.flutter.embedding.android.FlutterFragmentActivity
  class MainActivity: FlutterFragmentActivity() {
 }

também damos permissão para usar local_auth, adicione essas linhas em AndroidManifest.xml.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.app">
  <uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<manifest>

 

Para verificar se a autenticação local está disponível neste dispositivo.

Future<void> _checkBiometric() async {
  bool canCheckBiometric = false;

  try {
    canCheckBiometric = await auth.canCheckBiometrics;
  } on PlatformException catch (e) {
    print(e);
  }

  if (!mounted) return;
  setState(() {
    _canCheckBiometric = canCheckBiometric;
  }
  );
}

Criamos uma variável final com o nome auth na qual passamos LocalAuthentication().

final auth = LocalAuthentication();

Para obter a lista de biometria registrada neste dispositivo, criamos uma lista que é biometricType.

Future _getAvailableBiometric() async {
  List<BiometricType> availableBiometric = [];

  try {
    availableBiometric = await auth.getAvailableBiometrics();
  } on PlatformException catch (e) {
    print(e);
  }

  setState(() {
    _availableBiometric = availableBiometric;
  });
}

Crie também uma variável String para inspecionar a biometria, seja bem-sucedida ou malsucedida. Então criamos um método, e na partida, passamos autenticado como falso. e depois definimos autenticação com biometria.

E use os parâmetros dele, localizadoReason no qual definimos a string, defina useErrorDialogs como true e defina stickyAuth como true. neste método, também verificamos se a biométrica está autenticada ou não.

Future<void> _authenticate() async {
  bool authenticated = false;
  try {
    authenticated = await auth.authenticateWithBiometrics(
        localizedReason: "Scan your finger to authenticate",
        useErrorDialogs: true,
        stickyAuth: true);
  } on PlatformException catch (e) {
    print(e);
  }
  setState(() {
    authorized =
        authenticated ? "Authorized success" : "Failed to authenticate";
    print(authorized);
  });
}

Depois de criar todos esses métodos, chame-os para initState().

@override
void initState() {
  _checkBiometric();
  _getAvailableBiometric();

  super.initState();
}

Vamos para a parte da interface do usuário. Na parte da interface do usuário, retorne o scaffold em buildContext. add deu a cor de fundo da Tela. No corpo da passagem do Scaffold Column(), pegue o texto como filho,

e passar o texto de Login. Crie um FloatingActionButton e passe _authenticate em onPressed.

@override
Widget build(BuildContext context) {
  return Scaffold(
    backgroundColor: Colors.blueGrey.shade600,
    body: Padding(
      padding: const EdgeInsets.symmetric(vertical: 12.0,     horizontal: 24.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Center(
            child: Text(
              "Login",
              style: TextStyle(
                color: Colors.white,
                fontSize: 48.0,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
          Container(
            margin: const EdgeInsets.symmetric(vertical: 50.0),
            child: Column(
              children: [
                Container(
                  margin: const EdgeInsets.symmetric(
                   vertical: 15.0),
                  child: const Text(
                    "Authenticate using your fingerprint instead of    
your password",
                    textAlign: TextAlign.center,
                    style: TextStyle(color: Colors.white, 
                   height: 1.5),
                  ),
                ),
                Container(
                  margin: const EdgeInsets.symmetric(
                  vertical: 15.0),
                  width: double.infinity,
                  child: FloatingActionButton(
                    onPressed: _authenticate,
                    elevation: 0.0,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(30.0),
                    ),
                    child: const Padding(
                      padding: EdgeInsets.symmetric(
                          horizontal: 24.0, vertical: 14.0),
                      child: Text(
                        "Authenticate",
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                )
              ],
            ),
          )
        ],
      ),
    ),
  );
}

Quando executamos o aplicativo, devemos obter a saída da tela como a captura de tela abaixo.

finger_print_auth.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:local_auth/local_auth.dart';

class FingerprintAuth extends StatefulWidget {
  const FingerprintAuth({Key? key}) : super(key: key);

  @override
  _FingerprintAuthState createState() => _FingerprintAuthState();
}

class _FingerprintAuthState extends State<FingerprintAuth> {
  final auth = LocalAuthentication();
  String authorized = " not authorized";
  bool _canCheckBiometric = false;
  late List<BiometricType> _availableBiometric;

  Future<void> _authenticate() async {
    bool authenticated = false;

    try {
      authenticated = await auth.authenticateWithBiometrics(
          localizedReason: "Scan your finger to authenticate",
          useErrorDialogs: true,
          stickyAuth: true);
    } on PlatformException catch (e) {
      print(e);
    }

    setState(() {
      authorized =
          authenticated ? "Authorized success" : "Failed to authenticate";
      print(authorized);
    });
  }

  Future<void> _checkBiometric() async {
    bool canCheckBiometric = false;

    try {
      canCheckBiometric = await auth.canCheckBiometrics;
    } on PlatformException catch (e) {
      print(e);
    }

    if (!mounted) return;

    setState(() {
      _canCheckBiometric = canCheckBiometric;
    });
  }

  Future _getAvailableBiometric() async {
    List<BiometricType> availableBiometric = [];

    try {
      availableBiometric = await auth.getAvailableBiometrics();
    } on PlatformException catch (e) {
      print(e);
    }

    setState(() {
      _availableBiometric = availableBiometric;
    });
  }

  @override
  void initState() {
    _checkBiometric();
    _getAvailableBiometric();

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blueGrey.shade600,
      body: Padding(
        padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Center(
              child: Text(
                "Login",
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 48.0,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
            Container(
              margin: const EdgeInsets.symmetric(vertical: 50.0),
              child: Column(
                children: [
                  Container(
                    margin: const EdgeInsets.symmetric(vertical: 15.0),
                    child: const Text(
                      "Authenticate using your fingerprint instead of your password",
                      textAlign: TextAlign.center,
                      style: TextStyle(color: Colors.white, height: 1.5),
                    ),
                  ),
                  Container(
                    margin: const EdgeInsets.symmetric(vertical: 15.0),
                    width: double.infinity,
                    child: FloatingActionButton(
                      onPressed: _authenticate,
                      elevation: 0.0,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(30.0),
                      ),
                      child: const Padding(
                        padding: EdgeInsets.symmetric(
                            horizontal: 24.0, vertical: 14.0),
                        child: Text(
                          "Authenticate",
                          style: TextStyle(color: Colors.white),
                        ),
                      ),
                    ),
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:local_auth/local_auth.dart';

import 'finger_print_auth.dart';

void main()=> runApp(MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "Fingerprint Auth",
      home: FingerprintAuth(),
    );
  }
}

 

 

Conclusão:

Neste artigo, explicamos por que a biometria é importante e como implementá-la em qualquer projeto Flutter. E também aprenda a importância do local_auth e quantos tipos de biométrica existem neste pacote.

❤ Obrigado por ler este artigo ❤❤

Se eu entendi algo errado? Deixe-me saber nos comentários. Eu adoraria melhorar.