Dodaj przepływ uwierzytelniania użytkownika do aplikacji Flutter za pomocą FirebaseUI

1. Zanim zaczniesz

Podczas tych zajęć z programowania dowiesz się, jak dodać uwierzytelnianie Firebase do aplikacji Flutter przy użyciu pakietu interfejsu użytkownika FlutterFire. Dzięki temu pakietowi dodasz do aplikacji Flutter zarówno uwierzytelnianie za pomocą adresu e-mail/hasła, jak i uwierzytelnianie za pomocą logowania Google. Dowiesz się także, jak skonfigurować projekt Firebase i używać interfejsu CLI FlutterFire do inicjowania Firebase w aplikacji Flutter.

Warunki wstępne

W tym ćwiczeniu z programowania założono, że masz pewne doświadczenie z Flutterem. Jeśli nie, może najpierw naucz się podstaw. Pomocne są następujące linki:

Powinieneś także mieć pewne doświadczenie z Firebase, ale nie ma problemu, jeśli nigdy nie dodałeś Firebase do projektu Flutter. Jeśli nie znasz konsoli Firebase lub jesteś całkowicie nowy w Firebase, najpierw zapoznaj się z poniższymi linkami:

Co stworzysz

To ćwiczenie z programowania przeprowadzi Cię przez proces tworzenia przepływu uwierzytelniania dla aplikacji Flutter przy użyciu Firebase do uwierzytelniania. Aplikacja będzie zawierać ekran logowania, ekran „Zarejestruj się”, ekran odzyskiwania hasła i ekran profilu użytkownika.

6604fc9157f2c6ae.pngeab9509a41074930.pngda49189a5838e0bb.pngb2ccfb3632b77878.png

Czego się dowiesz

To ćwiczenie z kodowania obejmuje:

  • Dodawanie Firebase do aplikacji Flutter
  • Konfiguracja konsoli Firebase
  • Korzystanie z interfejsu wiersza polecenia Firebase w celu dodania Firebase do aplikacji
  • Używanie FlutterFire CLI do generowania konfiguracji Firebase w Dart
  • Dodawanie uwierzytelniania Firebase do aplikacji Flutter
  • Konfiguracja uwierzytelniania Firebase w konsoli
  • Dodawanie adresu e-mail i hasła Zaloguj się za pomocą pakietu firebase_ui_auth
  • Dodanie rejestracji użytkownika za pomocą pakietu firebase_ui_auth
  • Dodanie opcji „Zapomniałeś hasła?” strona
  • Dodawanie logowania Google za pomocą firebase_ui_auth
  • Konfigurowanie aplikacji do współpracy z wieloma dostawcami logowania.
  • Dodanie ekranu profilu użytkownika do aplikacji za pomocą pakietu firebase_ui_auth

To ćwiczenie z programowania dotyczy w szczególności dodania solidnego systemu uwierzytelniania przy użyciu pakietu firebase_ui_auth . Jak zobaczysz, całą tę aplikację ze wszystkimi powyższymi funkcjami można zaimplementować za pomocą około 100 linii kodu.

Co będziesz potrzebował

  • Praktyczna znajomość Flutter i zainstalowanego pakietu SDK
  • Edytor tekstu (JetBrains IDE, Android Studio i VS Code są obsługiwane przez Flutter)
  • Przeglądarka Google Chrome lub inny preferowany cel rozwoju Flutter. (Niektóre polecenia terminala w tym ćwiczeniu z programowania zakładają, że uruchamiasz aplikację w przeglądarce Chrome)

2. Utwórz i skonfiguruj projekt Firebase

Pierwszym zadaniem, które musisz wykonać, jest utworzenie projektu Firebase w konsoli internetowej Firebase.

Utwórz projekt Firebase

  1. Zaloguj się do Firebase .
  2. W konsoli Firebase kliknij Dodaj projekt (lub Utwórz projekt ) i wprowadź nazwę swojego projektu Firebase (na przykład „ FlutterFire-UI-Codelab ”).

df42a5e3d9584b48.png

  1. Kliknij opcje tworzenia projektu. Jeśli pojawi się monit, zaakceptuj warunki Firebase. Pomiń konfigurowanie Google Analytics, ponieważ nie będziesz używać Analytics w tej aplikacji.

d1fcec48bf251eaa.png

Aby dowiedzieć się więcej o projektach Firebase, zobacz Omówienie projektów Firebase .

Aplikacja, którą tworzysz, korzysta z uwierzytelniania Firebase , aby umożliwić użytkownikom logowanie się do Twojej aplikacji. Umożliwia także rejestrację nowym użytkownikom z poziomu aplikacji Flutter.

Uwierzytelnianie Firebase należy włączyć za pomocą konsoli Firebase, a po włączeniu wymaga specjalnej konfiguracji.

Włącz logowanie e-mailem dla uwierzytelniania Firebase

Aby umożliwić użytkownikom logowanie się do aplikacji internetowej, najpierw użyj metody logowania za pomocą adresu e-mail/hasła . Później dodasz metodę logowania Google .

  1. W konsoli Firebase rozwiń menu Kompilacja w lewym panelu.
  2. Kliknij opcję Uwierzytelnianie , a następnie kliknij przycisk Rozpocznij , a następnie zakładkę Metoda logowania (lub kliknij tutaj , aby przejść bezpośrednio do karty Metoda logowania ).
  3. Kliknij opcję E-mail/hasło na liście dostawców logowania , ustaw przełącznik Włącz w pozycji włączonej, a następnie kliknij przycisk Zapisz . 58e3e3e23c2f16a4.png

3. Skonfiguruj aplikację Flutter

Zanim zaczniemy, musisz pobrać kod startowy i zainstalować interfejs CLI Firebase.

Zdobądź kod startowy

Sklonuj repozytorium GitHub z wiersza poleceń:

git clone https://github.com/flutter/codelabs.git flutter-codelabs

Alternatywnie, jeśli masz zainstalowane narzędzie CLI GitHuba :

gh repo clone flutter/codelabs flutter-codelabs

Przykładowy kod należy sklonować do katalogu flutter-codelabs na komputerze, który zawiera kod kolekcji codelabs. Kod tego ćwiczenia z programowania znajduje się w podkatalogu flutter-codelabs/firebase-auth-flutterfire-ui .

Katalog flutter-codelabs/firebase-auth-flutterfire-ui zawiera dwa projekty Flutter. Jeden nazywa się complete , a drugi start . Katalog start zawiera niekompletny projekt i to tam spędzisz najwięcej czasu.

cd flutter-codelabs/firebase-auth-flutterfire-ui/start

Jeśli chcesz przejść dalej lub zobaczyć, jak coś powinno wyglądać po ukończeniu, zajrzyj do katalogu o nazwie Complete w celu uzyskania odsyłaczy.

Jeśli chcesz kontynuować ćwiczenia z programowania i samodzielnie dodać kod, powinieneś zacząć od aplikacji Flutter pod adresem flutter-codelabs/firebase-auth-flutterfire-ui/start i dodawać kod do tego projektu w trakcie ćwiczeń z programowania. Otwórz lub zaimportuj ten katalog do preferowanego IDE.

Zainstaluj interfejs wiersza polecenia Firebase

Interfejs Firebase CLI udostępnia narzędzia do zarządzania projektami Firebase. Interfejs CLI jest wymagany dla interfejsu CLI FlutterFire, który zainstalujesz za chwilę.

Istnieje wiele sposobów instalacji interfejsu CLI. Najprostszym sposobem, jeśli używasz systemu MacOS lub Linux, jest uruchomienie tego polecenia na terminalu:

curl -sL https://firebase.tools | bash

Po zainstalowaniu interfejsu CLI musisz uwierzytelnić się w Firebase.

  1. Zaloguj się do Firebase przy użyciu swojego konta Google, uruchamiając następujące polecenie:
firebase login
  1. To polecenie łączy komputer lokalny z Firebase i zapewnia dostęp do projektów Firebase.
  1. Sprawdź, czy interfejs CLI jest poprawnie zainstalowany i ma dostęp do Twojego konta, wyświetlając listę projektów Firebase. Uruchom następujące polecenie:
firebase projects:list
  1. Wyświetlana lista powinna być taka sama, jak projekty Firebase wymienione w konsoli Firebase . Powinieneś zobaczyć przynajmniej flutterfire-ui-codelab.

Zainstaluj interfejs wiersza polecenia FlutterFire

FlutterFire CLI to narzędzie, które pomaga uprościć proces instalacji Firebase na wszystkich obsługiwanych platformach w aplikacji Flutter. Jest zbudowany na bazie Firebase CLI.

Najpierw zainstaluj CLI:

dart pub global activate flutterfire_cli

Upewnij się, że interfejs CLI został zainstalowany. Uruchom następujące polecenie i upewnij się, że interfejs CLI wyświetla menu pomocy.

flutterfire -—help

Dodaj swój projekt Firebase do aplikacji Flutter

Skonfiguruj FlutterFire

Możesz użyć FlutterFire do wygenerowania kodu Dart potrzebnego do korzystania z Firebase w aplikacji Flutter.

flutterfire configure

Po uruchomieniu tego polecenia zostaniesz poproszony o wybranie projektu Firebase, którego chcesz używać i platform, które chcesz skonfigurować.

Poniższe zrzuty ekranu przedstawiają monity, na które należy odpowiedzieć.

  1. Wybierz projekt, którego chcesz użyć. W takim przypadku użyj flutterfire-ui-codelab 1359cdeb83204baa.png
  2. Wybierz platformy, z których chcesz korzystać. W tym ćwiczeniu z programowania przedstawiono kroki konfiguracji uwierzytelniania Firebase dla Flutter w Internecie, iOS i Androidzie, ale możesz skonfigurować swój projekt Firebase tak, aby korzystał ze wszystkich opcji. 301c9534f594f472.png
  3. Ten zrzut ekranu przedstawia wynik na końcu procesu. Jeśli znasz Firebase, zauważysz, że nie musisz tworzyć aplikacji platformowych (na przykład aplikacji na Androida) w konsoli, a FlutterFire CLI zrobił to za Ciebie. 12199a85ade30459.png

Kiedy już to zrobisz, spójrz na aplikację Flutter w swoim edytorze tekstu. FlutterFire CLI wygenerował nowy plik o nazwie firebase_options.dart . Ten plik zawiera klasę o nazwie FirebaseOptions, która zawiera zmienne statyczne przechowujące konfigurację Firebase wymaganą dla każdej platformy. Jeśli po uruchomieniu flutterfire configure wybrałeś wszystkie platformy, zobaczysz statyczne wartości o nazwach web , android , ios i macos .

firebase_options.dart

import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
   show defaultTargetPlatform, kIsWeb, TargetPlatform;

/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
///   options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
 static FirebaseOptions get currentPlatform {
   if (kIsWeb) {
     return web;
   }
   // ignore: missing_enum_constant_in_switch
   switch (defaultTargetPlatform) {
     case TargetPlatform.android:
       return android;
     case TargetPlatform.iOS:
       return ios;
     case TargetPlatform.macOS:
       return macos;
   }

   throw UnsupportedError(
     'DefaultFirebaseOptions are not supported for this platform.',
   );
 }

 static const FirebaseOptions web = FirebaseOptions(
   apiKey: 'AIzaSyCqFjCV_9CZmYeIvcK9FVy4drmKUlSaIWY',
   appId: '1:963656261848:web:7219f7fca5fc70afb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   authDomain: 'flutterfire-ui-codelab.firebaseapp.com',
   storageBucket: 'flutterfire-ui-codelab.appspot.com',
   measurementId: 'G-DGF0CP099H',
 );

 static const FirebaseOptions android = FirebaseOptions(
   apiKey: 'AIzaSyDconZaCQpkxIJ5KQBF-3tEU0rxYsLkIe8',
   appId: '1:963656261848:android:c939ccc86ab2dcdbb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.appspot.com',
 );

 static const FirebaseOptions ios = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.appspot.com',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );

 static const FirebaseOptions macos = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.appspot.com',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );
}

Firebase używa słowa aplikacja w odniesieniu do konkretnej kompilacji dla określonej platformy w projekcie Firebase. Na przykład projekt Firebase o nazwie FlutterFire-ui-codelab ma wiele aplikacji: jedną dla Androida, jedną dla iOS, jedną dla MacOS i jedną dla Internetu.

Metoda DefaultFirebaseOptions.currentPlatform wykorzystuje wyliczenie TargetPlatform udostępnione przez Flutter w celu wykrycia platformy, na której działa Twoja aplikacja, a następnie zwraca wartości konfiguracyjne Firebase potrzebne dla prawidłowej aplikacji Firebase.

Dodaj pakiety Firebase do aplikacji Flutter

Ostatnim krokiem konfiguracji jest dodanie odpowiednich pakietów Firebase do projektu Flutter. Plik firebase_options.dart powinien zawierać błędy, ponieważ opiera się na pakietach Firebase, które nie zostały jeszcze dodane. W terminalu upewnij się, że jesteś w katalogu głównym projektu Flutter pod adresem flutter-codelabs/firebase-emulator-suite/start . Następnie uruchom trzy następujące polecenia:

flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add firebase_ui_auth

To jedyne pakiety, których potrzebujesz w tym momencie.

Zainicjuj Firebase

Aby skorzystać z dodanych pakietów oraz DefaultFirebaseOptions.currentPlatform, należy zaktualizować kod w funkcji main w pliku main.dart .

główna.rzutka

void main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp(
   options: DefaultFirebaseOptions.currentPlatform,
 );


 runApp(const MyApp());
}

Ten kod robi dwie rzeczy.

  1. WidgetsFlutterBinding.ensureInitialized() informuje Flutter, aby nie uruchamiał kodu widżetu aplikacji, dopóki środowisko Flutter nie zostanie całkowicie uruchomione. Firebase korzysta z natywnych kanałów platformy, które wymagają działania frameworka.
  2. Firebase.initializeApp konfiguruje połączenie między aplikacją Flutter a projektem Firebase. DefaultFirebaseOptions.currentPlatform jest importowana z wygenerowanego przez nas pliku firebase_options.dart . Ta wartość statyczna wykrywa platformę, na której używasz, i przekazuje odpowiednie klucze Firebase.

4. Dodaj początkową stronę uwierzytelniania interfejsu Firebase

Interfejs użytkownika Firebase dla uwierzytelniania udostępnia widżety reprezentujące całe ekrany aplikacji. Te ekrany obsługują różne procesy uwierzytelniania w aplikacji, takie jak logowanie, rejestracja, zapomniałem hasła, profil użytkownika i inne. Na początek dodaj do swojej aplikacji stronę docelową, która będzie pełnić funkcję strażnika uwierzytelniania w aplikacji głównej.

Materiał lub aplikacja Cupertino

Interfejs użytkownika FlutterFire wymaga, aby aplikacja była opakowana w aplikację MaterialApp lub CupertinoApp. W zależności od dokonanego wyboru interfejs użytkownika automatycznie odzwierciedli różnice między widżetami Material lub Cupertino. W przypadku tych zajęć z kodowania użyj MaterialApp , który jest już dodany do aplikacji w app.dart .

aplikacja.dart

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

class MyApp extends StatelessWidget {
 const MyApp({super.key});
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     theme: ThemeData(
       primarySwatch: Colors.blue,
     ),
     home: const AuthGate(),
   );
 }
}

Sprawdź stan uwierzytelnienia

Zanim będzie można wyświetlić ekran logowania, należy ustalić, czy użytkownik jest obecnie uwierzytelniony. Najczęstszym sposobem sprawdzenia tego jest odsłuchanie authStateChanges FirebaseAuth przy użyciu wtyczki Firebase Auth .

W powyższym przykładzie kodu MaterialApp buduje widżet AuthGate w swojej metodzie kompilacji. (To jest niestandardowy widget, który nie jest udostępniany przez interfejs FlutterFire.)

Ten widżet należy zaktualizować, aby zawierał strumień authStateChanges .

Interfejs API authStateChanges zwraca Stream z bieżącym użytkownikiem (jeśli jest zalogowany) lub null, jeśli nie jest. Aby subskrybować ten stan w naszej aplikacji, możesz skorzystać z widżetu StreamBuilder firmy Flutter i przekazać do niego strumień.

StreamBuilder to widżet, który buduje się na podstawie najnowszej migawki danych ze strumienia , który mu przekazujesz. Automatycznie odbudowuje się, gdy strumień wyemituje nową migawkę.

Zaktualizuj kod w auth_gate.dart .

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
  const AuthGate({super.key});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [],
          );
        }

        return const HomeScreen();
      },
    );
  }
}
  • StreamBuilder.stream jest przekazywany FirebaseAuth.instance.authStateChanged , wspomniany strumień, który zwróci obiekt User Firebase, jeśli użytkownik się uwierzytelnił. (W przeciwnym razie zwróci null .)
  • Następnie kod używa snapshot.hasData do sprawdzenia, czy wartość ze strumienia zawiera obiekt User .
  • Jeśli nie, zwróci widżet SignInScreen . Obecnie ten ekran nic nie da. Zostanie to zaktualizowane w następnym kroku.
  • W przeciwnym razie zwraca HomeScreen , który jest główną częścią aplikacji, do której dostęp mają tylko uwierzytelnieni użytkownicy.

SignInScreen to widżet pochodzący z pakietu interfejsu FlutterFire. Na tym skupimy się w następnym kroku ćwiczeń z kodowania. Po uruchomieniu aplikacji w tym momencie powinien zostać wyświetlony pusty ekran logowania.

5. Ekran logowania

Widżet SignInScreen udostępniany przez interfejs użytkownika FlutterFire dodaje następującą funkcjonalność:

  • Umożliwia użytkownikom logowanie się
  • Jeśli użytkownicy zapomnieli hasła, mogą kliknąć opcję „Zapomniałeś hasła?” i zostaniesz przeniesiony do formularza umożliwiającego zresetowanie hasła
  • Jeżeli użytkownik nie jest jeszcze zarejestrowany, może kliknąć „Zarejestruj się” i przejść do innego formularza umożliwiającego rejestrację.

Ponownie wymaga to tylko kilku linii kodu. Przywołaj kod w widżecie AuthGate:

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
  const AuthGate({super.key});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [
              EmailAuthProvider(), // new
            ],
          );
        }

        return const HomeScreen();
      },
    );
  }
}

Widżet SignInScreen i jego argument providers to jedyny kod wymagany do uzyskania wszystkich wyżej wymienionych funkcjonalności. Powinieneś teraz zobaczyć ekran logowania, na którym można wpisać „e-mail” i „hasło”, a także przycisk „Zaloguj się”.

Choć funkcjonalny, brakuje mu stylu. Widget udostępnia parametry umożliwiające dostosowanie wyglądu ekranu logowania. Możesz na przykład dodać logo swojej firmy.

Dostosuj ekran logowania

Konstruktor nagłówków

Używając argumentu SignInScreen.headerBuilder , możesz dodać dowolne widżety nad formularzem logowania. Zaktualizuj plik auth_gate.dart za pomocą tego kodu:

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('assets/flutterfire_300x.png'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

Argument headerBuilder wymaga funkcji typu HeaderBuilder, która jest zdefiniowana w pakiecie interfejsu użytkownika FlutterFire.

typedef HeaderBuilder = Widget Function(
 BuildContext context,
 BoxConstraints constraints,
 double shrinkOffset,
);

Ponieważ jest to wywołanie zwrotne, udostępnia wartości, których możesz użyć, takie jak BuildContext i BoxConstraints , i wymaga zwrócenia widżetu. Niezależnie od tego, który zwrócisz widżet, zostanie wyświetlony u góry ekranu. W tym przykładzie nowy kod dodaje obraz na górze ekranu. Twoja aplikacja powinna teraz wyglądać tak.

73d7548d91bbd2ab.png

Kreator napisów

Ekran logowania udostępnia trzy dodatkowe parametry, które pozwalają dostosować ekran: subtitleBuilder , footerBuilder i sideBuilder .

subtitleBuilder różni się nieco tym, że argumenty wywołania zwrotnego obejmują akcję typu AuthAction . AuthAction to wyliczenie, którego można użyć do sprawdzenia, czy ekran, na którym znajduje się użytkownik, to ekran „logowania”, czy ekran „rejestracji”.

Zaktualizuj kod w pliku auth_gate.dart, aby użyć narzędzia subtitleBuilder.

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
              EmailAuthProvider()
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

Załaduj ponownie aplikację i powinna wyglądać tak

Argument footerBuilder jest taki sam jak subtitleBuilder. Nie ujawnia BoxConstraints ani shrinkOffset , ponieważ jest przeznaczony dla tekstu, a nie obrazów. (Chociaż możesz dodać dowolny widżet, jaki chcesz.)

Dodaj stopkę do ekranu logowania za pomocą tego kodu.

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider()
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }}

Konstruktor boczny

Argument SignInScreen.sidebuilder akceptuje wywołanie zwrotne i tym razem argumentami tego wywołania zwrotnego są BuildContext i double shrinkOffset . Widżet zwrócony przez sideBuilder będzie wyświetlany po lewej stronie formularza logowania i tylko na szerokich ekranach. Oznacza to, że widżet będzie wyświetlany tylko w aplikacjach komputerowych i internetowych.

Wewnętrznie interfejs FlutterFire używa punktu przerwania, aby określić, czy zawartość nagłówka powinna być wyświetlana (na wysokich ekranach, np. mobilnych), czy powinna być wyświetlana treść boczna (na szerokich ekranach, komputerze stacjonarnym lub w Internecie). W szczególności, jeśli ekran ma więcej niż 800 pikseli szerokości, wyświetlana jest zawartość kreatora strony, a zawartość nagłówka nie. Jeśli szerokość ekranu jest mniejsza niż 800 pikseli, sytuacja jest odwrotna.

Zaktualizuj kod w pliku auth_gate.dart, aby dodać widżety sideBuilder.

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }
       return const HomeScreen();
     },
   );
 }
}

Twoja aplikacja powinna teraz wyglądać tak po powiększeniu szerokości okna (jeśli używasz Flutter web lub MacOS).

8dc60b4e5d7dd2d0.png

Utwórz użytkownika

W tym momencie cały kod tego ekranu jest już gotowy. Zanim jednak będziesz mógł się zalogować, musisz utworzyć użytkownika. Możesz to zrobić na ekranie „Zarejestruj się” lub możesz utworzyć użytkownika w konsoli Firebase.

Aby skorzystać z konsoli:

  1. Przejdź do tabeli „Użytkownicy” w konsoli Firebase.
  2. Kliknij tutaj
  3. Wybierz „flutterfire-ui-codelab” (lub inny projekt, jeśli użyłeś innej nazwy). Zobaczysz tę tabelę:

f038fd9a58ed60d9.png

  1. Kliknij przycisk „Dodaj użytkownika”.

2d78390d4c5dbbfa.png

  1. Wprowadź adres e-mail i hasło nowego użytkownika. Może to być fałszywy adres e-mail i hasło, które wpisałem na obrazku poniżej. To zadziała, ale funkcja „Zapomniałem hasła” nie będzie działać, jeśli użyjesz fałszywego adresu e-mail.

62ba0feb33d54add.png

  1. Kliknij „Dodaj użytkownika”

32b236b3ef94d4c7.png

Teraz możesz wrócić do aplikacji Flutter i zalogować użytkownika za pośrednictwem strony logowania. Twoja aplikacja powinna wyglądać tak:

dd43d260537f3b1a.png

6. Ekran profilu

Interfejs użytkownika FlutterFire zapewnia również widżet ProfileScreen , który ponownie zapewnia wiele funkcji w kilku linijkach kodu.

Dodaj widżet ProfileScreen

Przejdź do pliku home.dart w edytorze tekstu. Zaktualizuj go za pomocą tego kodu:

Strona główna.dart

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

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => const ProfileScreen(),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Nowy kod uwagi to wywołanie zwrotne przekazywane do IconButton.isPressed method. Po naciśnięciu tego IconButton aplikacja tworzy nową anonimową trasę i prowadzi do niej. Na tej trasie zostanie wyświetlony widżet ProfileScreen , który jest zwracany przez wywołanie zwrotne MaterialPageRoute.builder .

Załaduj ponownie aplikację i naciśnij ikonę w prawym górnym rogu (na pasku aplikacji), a wyświetli się taka strona:

36487fc4ab4f26a7.png

Jest to standardowy interfejs użytkownika udostępniany na stronie interfejsu użytkownika FlutterFire. Wszystkie przyciski i pola tekstowe są połączone z Firebase Auth i działają od razu po wyjęciu z pudełka. Na przykład możesz wpisać nazwę w polu tekstowym „Nazwa”, a interfejs użytkownika FlutterFire wywoła metodę FirebaseAuth.instance.currentUser?.updateDisplayName , która zapisze tę nazwę w Firebase.

Wylogowanie

W tej chwili, jeśli naciśniesz przycisk „Wyloguj się”, aplikacja nie ulegnie zmianie. Spowoduje to wylogowanie, ale nie nastąpi powrót do widżetu AuthGate. Aby to zaimplementować, użyj parametru ProfileScreen.actions.

Najpierw zaktualizuj kod w home.dart.

Strona główna.dart

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

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => ProfileScreen(
                    actions: [
                      SignedOutAction((context) {
                        Navigator.of(context).pop();
                      })
                    ],
                  ),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Teraz, tworząc instancję ProfileScreen , przekazujesz jej także listę akcji do argumentu ProfileScreen.actions . Te akcje są typu FlutterFireUiAction . Istnieje wiele różnych klas, które są podtypami FlutterFireUiAction i ogólnie używasz ich, aby poinformować aplikację, aby reagowała na różne zmiany stanu uwierzytelniania. SignedOutAction wywołuje funkcję wywołania zwrotnego, którą podajesz, gdy stan uwierzytelnienia Firebase zmieni się na wartość null bieżącego użytkownika.

Dodając wywołanie zwrotne wywołujące Navigator.of(context).pop() po wyzwoleniu SignedOutAction, aplikacja przejdzie do poprzedniej strony. W tej przykładowej aplikacji istnieje tylko jedna stała trasa, która pokazuje stronę logowania, jeśli nie jest zalogowany użytkownik, oraz stronę główną, jeśli jest użytkownik. Dzieje się tak, gdy użytkownik się wyloguje, w aplikacji zostanie wyświetlona strona logowania.

Dostosuj stronę profilu

Podobnie jak w przypadku strony logowania, stronę profilu można dostosować. Po pierwsze, na naszej bieżącej stronie nie ma możliwości powrotu do strony głównej, gdy użytkownik znajdzie się na stronie profilu. Napraw ten problem, nadając widżetowi ProfileScreen pasek aplikacji.

Strona główna.dart

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

class HomeScreen extends StatelessWidget {
 const HomeScreen({super.key});

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       actions: [
         IconButton(
           icon: const Icon(Icons.person),
           onPressed: () {
             Navigator.push(
               context,
               MaterialPageRoute<ProfileScreen>(
                 builder: (context) => ProfileScreen(
                   appBar: AppBar(
                     title: const Text('User Profile'),
                   ),
                   actions: [
                     SignedOutAction((context) {
                       Navigator.of(context).pop();
                     })
                   ],
                 ),
               ),
             );
           },
         )
       ],
       automaticallyImplyLeading: false,
     ),
     body: Center(
       child: Column(
         children: [
           Image.asset('dash.png'),
           Text(
             'Welcome!',
             style: Theme.of(context).textTheme.displaySmall,
           ),
           const SignOutButton(),
         ],
       ),
     ),
   );
 }
}

Argument ProfileScreen.appBar akceptuje widżet AppBar z pakietu Flutter Material, dzięki czemu można go traktować jak każdy inny AppBar który zbudowałeś i przekazałeś do Scaffold . W tym przykładzie zachowano domyślną funkcję automatycznego dodawania przycisku „wstecz”, a ekran ma teraz tytuł.

Dodaj dzieci do ekranu profilu

Widget ProfileScreen ma również opcjonalny argument o nazwie dzieci. Ten argument akceptuje listę widżetów, które zostaną umieszczone pionowo wewnątrz widżetu Kolumna, który jest już używany wewnętrznie do tworzenia ekranu ProfileScreen. Ten widżet Kolumna w metodzie kompilacji ProfileScreen umieści przekazywane przez Ciebie elementy podrzędne nad przyciskiem „Wyloguj się”.

Zaktualizuj kod w home.dart, aby wyświetlić tutaj logo firmy, podobne do ekranu logowania.

Strona główna.dart

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

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => ProfileScreen(
                    appBar: AppBar(
                      title: const Text('User Profile'),
                    ),
                    actions: [
                      SignedOutAction((context) {
                        Navigator.of(context).pop();
                      })
                    ],
                    children: [
                      const Divider(),
                      Padding(
                        padding: const EdgeInsets.all(2),
                        child: AspectRatio(
                          aspectRatio: 1,
                          child: Image.asset('flutterfire_300x.png'),
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Załaduj ponownie aplikację, a na ekranie zobaczysz to:

ebe5792b765dbf87.png

7. Wieloplatformowe logowanie do uwierzytelniania Google

Interfejs FlutterFire zapewnia także widżety i funkcje umożliwiające uwierzytelnianie u zewnętrznych dostawców, takich jak Google, Twitter, Facebook, Apple i Github.

Aby zintegrować się z uwierzytelnianiem Google, zainstaluj oficjalną wtyczkę firebase_ui_oauth_google i jej zależności, które będą obsługiwać natywny przepływ uwierzytelniania. W terminalu przejdź do katalogu głównego projektu flutter i wprowadź następujące polecenie:

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Włącz dostawcę logowania Google

Następnie włącz dostawcę Google w konsoli Firebase :

  1. Przejdź do ekranu Dostawcy logowania do uwierzytelniania w konsoli.
  2. Kliknij „Dodaj nowego dostawcę”. 8286fb28be94bf30.png
  3. Wybierz „Google”. c4e28e6f4974be7f.png
  4. Przełącz przełącznik oznaczony „Włącz” i naciśnij „Zapisz”. e74ff86990763826.png
  5. Jeśli pojawi się modal z informacją o pobraniu plików konfiguracyjnych, kliknij „Gotowe”.
  6. Upewnij się, że dostawca logowania Google został dodany. 5329ce0543c90d95.png

Dodaj przycisk logowania Google

Po włączeniu logowania Google dodaj widżet potrzebny do wyświetlenia stylizowanego przycisku logowania Google na stronie logowania. Przejdź do pliku auth_gate.dart i zaktualizuj kod do następującego:

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart'; // new
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR_WEBCLIENT_ID"),  // new
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

Jedynym nowym kodem jest dodanie GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") do konfiguracji widżetu SignInScreen.

Po dodaniu załaduj ponownie aplikację, a zobaczysz przycisk logowania Google.

aca71a46a011bfb5.png

Skonfiguruj przycisk logowania

Przycisk nie działa bez dodatkowej konfiguracji. Jeśli programujesz za pomocą Flutter Web, jest to jedyny krok, który musisz dodać, aby to zadziałało. Inne platformy wymagają dodatkowych kroków, które zostaną omówione za chwilę.

  1. Przejdź do strony Dostawcy uwierzytelniania w konsoli Firebase .
  2. Kliknij dostawcę Google. 9b3a325c5eca6e49.png
  3. Kliknij panel rozszerzeń „Konfiguracja Web SDK”.
  4. Skopiuj wartość z „Identyfikatora klienta internetowego” 711a79f0d931c60f.png
  5. Wróć do edytora tekstu i zaktualizuj instancję GoogleProvider w pliku auth_gate.dart , przekazując ten identyfikator do parametru o nazwie clientId .
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

Po wprowadzeniu identyfikatora klienta internetowego załaduj ponownie aplikację. Po naciśnięciu przycisku „Zaloguj się przez Google” pojawi się nowe okno (jeśli korzystasz z Internetu), które przeprowadzi Cię przez proces logowania do Google. Początkowo wygląda to tak:

14e73e3c9de704bb.png

Skonfiguruj iOS

Aby to działało na iOS, istnieje dodatkowy proces konfiguracji.

  1. Przejdź do ekranu Ustawienia projektu w konsoli Firebase . Pojawi się karta z listą aplikacji Firebase, która wygląda następująco: fefa674acbf213cc.png
  2. Kliknij iOS. Pamiętaj, że nazwa Twojej aplikacji będzie inna niż moja. Tam, gdzie moje mówi „ukończone”, twoje powie „start”, jeśli użyłeś projektu flutter-codelabs/firebase-auth-flutterfire-ui/start do śledzenia tego ćwiczenia z kodowania.
  3. Kliknij przycisk „GoogleServices-Info.plist”, aby pobrać potrzebny plik konfiguracyjny. f89b3192871dfbe3.png
  4. Przeciągnij i upuść pobrany plik do katalogu o nazwie . /ios/Runner w twoim projekcie Flutter.
  5. Otwórz Xcode, uruchamiając następującą komendę terminala w katalogu głównym projektu:

otwórz ios/Runner.xcworkspace

  1. Kliknij prawym przyciskiem myszy katalog Runner i wybierz Dodaj pliki do „Runner”. 858986063a4c5201.png
  2. W menedżerze plików wybierz GoogleService-Info.plist.
  3. Wróć do edytora tekstu (który nie jest Xcode) i dodaj poniższe atrybuty CFBundleURLTypes do pliku [my_project]/ios/Runner/Info.plist.
<!-- Put me in the [my_project]/ios/Runner/Info.plist file -->
<!-- Google Sign-in Section -->
<key>CFBundleURLTypes</key>
<array>
        <dict>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLSchemes</key>
                <array>
                        <!-- TODO Replace this value: -->
                        <!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID -->
                        <string>com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppkn</string>
                </array>
        </dict>
</array>
<!-- End of the Google Sign-in Section -->

Jeśli Twoja aplikacja Flutter działa już w systemie iOS, musisz ją całkowicie zamknąć, a następnie ponownie uruchomić aplikację. W przeciwnym razie uruchom aplikację w systemie iOS.

8. Gratulacje!

Ukończyłeś interfejs Firebase Auth dla zajęć z programowania Flutter. Ukończony kod tego Codelaba znajdziesz w katalogu „complete” na githubie: Flutter Codelabs

Co omówiliśmy

  • Konfigurowanie aplikacji Flutter do korzystania z Firebase
  • Konfigurowanie projektu Firebase w konsoli Firebase
  • Interfejs FlutterFire
  • Interfejs wiersza polecenia Firebase
  • Korzystanie z uwierzytelniania Firebase
  • Używanie interfejsu użytkownika FlutterFire do łatwej obsługi uwierzytelniania Firebase w aplikacji Flutter

Następne kroki

Ucz się więcej

Sparky jest tutaj, aby świętować z Tobą!

2a0ad195769368b1.gif