Добавьте поток аутентификации пользователя в приложение Flutter с помощью FirebaseUI.

1. Прежде чем начать

В этой кодовой лаборатории вы узнаете, как добавить аутентификацию Firebase в ваше приложение Flutter с помощью пакета FlutterFire UI. С помощью этого пакета вы добавите как аутентификацию по электронной почте и паролю, так и аутентификацию Google Sign In в приложение Flutter. Вы также узнаете, как настроить проект Firebase и использовать FlutterFire CLI для инициализации Firebase в вашем приложении Flutter.

Предпосылки

Эта кодовая лаборатория предполагает, что у вас есть некоторый опыт работы с Flutter. Если нет, вам, возможно, стоит сначала изучить основы. Следующие ссылки будут полезны:

У вас также должен быть некоторый опыт работы с Firebase, но ничего страшного, если вы никогда не добавляли Firebase в проект Flutter. Если вы не знакомы с консолью Firebase или вообще новичок в Firebase, сначала ознакомьтесь со следующими ссылками:

Что вы создадите

Эта кодовая лаборатория проведет вас через создание потока аутентификации для приложения Flutter с использованием Firebase для аутентификации. Приложение будет иметь экран входа, экран «Регистрация», экран восстановления пароля и экран профиля пользователя.

6604fc9157f2c6ae.pngeab9509a41074930.pngda49189a5838e0bb.pngb2ccfb3632b77878.png

Чему вы научитесь

В этой лабораторной работе рассматриваются следующие вопросы:

  • Добавление Firebase в приложение Flutter
  • Настройка консоли Firebase
  • Использование Firebase CLI для добавления Firebase в ваше приложение
  • Использование FlutterFire CLI для генерации конфигурации Firebase в Dart
  • Добавление аутентификации Firebase в ваше приложение Flutter
  • Настройка аутентификации Firebase в консоли
  • Добавление входа по электронной почте и паролю с помощью пакета firebase_ui_auth
  • Добавление регистрации пользователя с помощью пакета firebase_ui_auth
  • Добавление страницы «Забыли пароль?»
  • Добавление входа через Google с помощью firebase_ui_auth
  • Настройка приложения для работы с несколькими поставщиками услуг входа.
  • Добавление экрана профиля пользователя в ваше приложение с помощью пакета firebase_ui_auth

Эта кодовая лаборатория специально посвящена добавлению надежной системы аутентификации с использованием пакета firebase_ui_auth . Как вы увидите, все это приложение со всеми вышеперечисленными функциями может быть реализовано примерно в 100 строках кода.

Что вам понадобится

  • Практические навыки работы с Flutter и установленный SDK
  • Текстовый редактор (Flutter поддерживает JetBrains IDE, Android Studio и VS Code)
  • Браузер Google Chrome или другая предпочитаемая вами цель разработки для Flutter. (Некоторые команды терминала в этой кодовой лаборатории предполагают, что вы запускаете свое приложение в Chrome)

2. Создайте и настройте проект Firebase

Первая задача, которую вам необходимо выполнить, — это создание проекта Firebase в веб-консоли Firebase.

Создать проект Firebase

  1. Войдите в Firebase .
  2. В консоли Firebase нажмите « Добавить проект » (или «Создать проект ») и введите имя для вашего проекта Firebase (например, « FlutterFire-UI-Codelab »). df42a5e3d9584b48.png
  3. Щелкните по параметрам создания проекта. Примите условия Firebase, если будет предложено. Пропустите настройку Google Analytics, поскольку вы не будете использовать Analytics для этого приложения. d1fcec48bf251eaa.png

Дополнительную информацию о проектах Firebase см. в разделе Понимание проектов Firebase .

Включить вход по электронной почте для аутентификации Firebase

Приложение, которое вы создаете, использует аутентификацию Firebase , чтобы позволить вашим пользователям входить в ваше приложение. Оно также позволяет новым пользователям регистрироваться из приложения Flutter.

Аутентификацию Firebase необходимо включить с помощью консоли Firebase, а после включения потребуется специальная настройка.

Чтобы разрешить пользователям входить в веб-приложение, сначала вы используете метод входа с помощью электронной почты/пароля . Позже вы добавите метод входа с помощью Google .

  1. В консоли Firebase разверните меню «Сборка» на левой панели.
  2. Нажмите «Аутентификация» , затем нажмите кнопку « Начать» , затем вкладку «Способ входа» (или перейдите сразу на вкладку «Способ входа »).
  3. Нажмите «Электронная почта/Пароль» в списке поставщиков услуг входа , установите переключатель «Включить» в положение «Вкл.», а затем нажмите « Сохранить ».

58e3e3e23c2f16a4.png

3. Настройте приложение Flutter

Прежде чем начать, вам необходимо загрузить стартовый код и установить Firebase CLI.

Получить стартовый код

Клонируйте репозиторий GitHub из командной строки:

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

Либо, если у вас установлен инструмент CLI GitHub :

gh repo clone flutter/codelabs flutter-codelabs

Код примера должен быть клонирован в каталог flutter-codelabs на вашем компьютере, который содержит код для коллекции codelabs. Код для этого codelab находится в подкаталоге flutter-codelabs/firebase-auth-flutterfire-ui .

Каталог flutter-codelabs/firebase-auth-flutterfire-ui содержит два проекта Flutter. Один называется complete , а другой — start . Каталог start содержит незавершенный проект, и именно на нем вы проведете большую часть времени.

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

Если вы хотите пропустить вперед или посмотреть, как что-то должно выглядеть после завершения, загляните в каталог с именем complete, чтобы найти перекрестную ссылку.

Если вы хотите следовать кодовой лаборатории и добавлять код самостоятельно, вам следует начать с приложения Flutter по адресу flutter-codelabs/firebase-auth-flutterfire-ui/start и добавлять код в этот проект по всему кодовой лаборатории. Откройте или импортируйте этот каталог в предпочитаемую вами IDE.

Установить Firebase CLI

Firebase CLI предоставляет инструменты для управления проектами Firebase. CLI требуется для FlutterFire CLI, который вы установите немного позже.

Существует множество способов установки CLI. Ознакомьтесь со всеми доступными вариантами для вашей операционной системы на firebase.google.com/docs/cli .

После установки CLI необходимо пройти аутентификацию в Firebase.

  1. Войдите в Firebase, используя свою учетную запись Google, выполнив следующую команду:
    firebase login
    
  2. Эта команда подключает ваш локальный компьютер к Firebase и предоставляет вам доступ к вашим проектам Firebase.
  3. Проверьте, что CLI установлен правильно и имеет доступ к вашей учетной записи, перечислив ваши проекты Firebase. Выполните следующую команду:
    firebase projects:list
    
  4. Отображаемый список должен быть таким же, как проекты Firebase, перечисленные в консоли Firebase . Вы должны увидеть как минимум flutterfire-ui-codelab.

Установите FlutterFire CLI

FlutterFire CLI — это инструмент, который помогает упростить процесс установки Firebase на всех поддерживаемых платформах в вашем приложении Flutter. Он построен поверх Firebase CLI.

Сначала установите CLI:

dart pub global activate flutterfire_cli

Убедитесь, что CLI установлен. Выполните следующую команду и убедитесь, что CLI выводит меню справки.

flutterfire --help

Добавьте свой проект Firebase в свое приложение Flutter

Настроить FlutterFire

Вы можете использовать FlutterFire для генерации необходимого кода Dart для использования Firebase в вашем приложении Flutter.

flutterfire configure

При запуске этой команды вам будет предложено выбрать, какой проект Firebase вы хотите использовать и какие платформы вы хотите настроить.

На следующих снимках экрана показаны вопросы, на которые вам нужно будет ответить.

  1. Выберите проект, который вы хотите использовать. В этом случае используйте flutterfire-ui-codelab 1359cdeb83204baa.png
  2. Выберите платформы, которые вы хотите использовать. В этой кодовой лаборатории есть шаги по настройке аутентификации Firebase для Flutter для веб-сайтов, iOS и Android, но вы можете настроить свой проект Firebase для использования всех опций. 301c9534f594f472.png
  3. На этом снимке экрана показан вывод в конце процесса. Если вы знакомы с Firebase, вы заметите, что вам не пришлось создавать приложения платформы (например, приложение Android) в консоли, а FlutterFire CLI сделал это за вас. 12199a85ade30459.png

Когда все будет готово, посмотрите на приложение Flutter в текстовом редакторе. FlutterFire CLI изменил файл firebase_options.dart . Этот файл содержит класс FirebaseOptions , который имеет статические переменные, содержащие конфигурацию Firebase, необходимую для каждой платформы. Если вы выбрали все платформы при запуске flutterfire configure , вы увидите статические значения с именами web , android , ios и macos .

lib/firebase_options.dart

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

class DefaultFirebaseOptions {
  static FirebaseOptions get currentPlatform {
    if (kIsWeb) {
      return web;
    }

    switch (defaultTargetPlatform) {
      case TargetPlatform.android:
        return android;
      case TargetPlatform.iOS:
        return ios;
      case TargetPlatform.macOS:
        return macos;
      default:
        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.firebasestorage.app',
    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.firebasestorage.app',
  );

  static const FirebaseOptions ios = FirebaseOptions(
    apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
    appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
    messagingSenderId: '963656261848',
    projectId: 'flutterfire-ui-codelab',
    storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
    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.firebasestorage.app',
    iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
    iosBundleId: 'com.example.complete',
  );
}

Firebase использует слово приложение для обозначения конкретной сборки для конкретной платформы в проекте Firebase. Например, проект Firebase под названием FlutterFire-ui-codelab имеет несколько приложений: одно для Android, одно для iOS, одно для macOS и одно для Web.

Метод DefaultFirebaseOptions.currentPlatform использует перечисление TargetPlatform , предоставляемое Flutter, для определения платформы, на которой работает ваше приложение, а затем возвращает значения конфигурации Firebase, необходимые для корректного приложения Firebase.

Добавьте пакеты Firebase в приложение Flutter

Последний шаг настройки — добавить соответствующие пакеты Firebase в ваш проект Flutter. Файл firebase_options.dart должен содержать ошибки, поскольку он опирается на пакеты Firebase, которые еще не добавлены. В терминале убедитесь, что вы находитесь в корне проекта Flutter по адресу flutter-codelabs/firebase-emulator-suite/start . Затем выполните три следующие команды:

flutter pub add firebase_core firebase_auth firebase_ui_auth

На данном этапе это единственные пакеты, которые вам понадобятся.

Инициализировать Firebase

Чтобы использовать добавленные пакеты и DefaultFirebaseOptions.currentPlatform, обновите код в функции main в файле main.dart .

lib/main.dart

import 'package:firebase_core/firebase_core.dart';                  // Add this import
import 'package:flutter/material.dart';

import 'app.dart';
import 'firebase_options.dart';                                     // And this import

// TODO(codelab user): Get API key
const clientId = 'YOUR_CLIENT_ID';

void main() async {
  // Add from here...
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  // To here.

  runApp(const MyApp(clientId: clientId));
}

Этот код выполняет две функции.

  1. WidgetsFlutterBinding.ensureInitialized() сообщает Flutter не начинать выполнение кода виджета приложения, пока фреймворк Flutter не будет полностью загружен. Firebase использует собственные каналы платформы, которые требуют, чтобы фреймворк был запущен.
  2. Firebase.initializeApp устанавливает соединение между вашим приложением Flutter и вашим проектом Firebase. DefaultFirebaseOptions.currentPlatform импортируется из нашего сгенерированного файла firebase_options.dart . Это статическое значение определяет, на какой платформе вы работаете, и передает соответствующие ключи Firebase.

4. Добавьте начальную страницу аутентификации Firebase UI

Firebase UI для Auth предоставляет виджеты, которые представляют целые экраны в вашем приложении. Эти экраны обрабатывают различные потоки аутентификации в вашем приложении, такие как «Вход», «Регистрация», «Забыли пароль», «Профиль пользователя» и т. д. Чтобы начать, добавьте в свое приложение целевую страницу, которая будет выступать в качестве защитника аутентификации для основного приложения.

Материал или приложение Купертино

FlutterFire UI требует, чтобы ваше приложение было обернуто либо в MaterialApp , либо CupertinoApp . В зависимости от вашего выбора UI автоматически отразит различия виджетов Material или Cupertino. Для этой кодовой лаборатории используйте MaterialApp , который уже добавлен в приложение в app.dart .

lib/app.dart

import 'package:flutter/material.dart';

import 'auth_gate.dart';

class MyApp extends StatelessWidget {
  const MyApp({super.key, required this.clientId});

  final String clientId;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: AuthGate(clientId: clientId),
    );
  }
}

Проверить состояние аутентификации

Прежде чем вы сможете отобразить экран входа, вам нужно определить, аутентифицирован ли пользователь. Самый распространенный способ проверить это — прослушать authStateChanges FirebaseAuth с помощью плагина Firebase Auth .

В приведенном выше примере кода MaterialApp создает виджет AuthGate в своем методе build . (Это пользовательский виджет, не предоставляемый FlutterFire UI.)

Этот виджет необходимо обновить, включив в него поток authStateChanges .

API authStateChanges возвращает Stream с текущим пользователем (если он вошел в систему) или null, если он не вошел. Чтобы подписаться на это состояние в нашем приложении, вы можете использовать виджет Flutter StreamBuilder и передать ему поток.

StreamBuilder — это виджет, который строит себя на основе последнего снимка данных из потока , который вы ему передаете. Он автоматически перестраивается, когда Stream выдает новый снимок.

Обновите код в auth_gate.dart .

lib/auth_gate.dart

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

import 'home.dart';

class AuthGate extends StatelessWidget {
  const AuthGate({super.key, required this.clientId});

  final String clientId;

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

        return const HomeScreen();
      },
    );                                                                 // To here.
  }
}
  • StreamBuilder.stream передается FirebaseAuth.instance.authStateChanged , вышеупомянутому потоку, который вернет объект Firebase User , если пользователь прошел аутентификацию, в противном случае он вернет null .
  • Далее код использует snapshot.hasData для проверки того, содержит ли значение из потока объект User .
  • Если его нет, он вернет виджет SignInScreen . На данный момент этот экран ничего не делает, он будет обновлен на следующем шаге.
  • В противном случае возвращается HomeScreen — основная часть приложения, доступ к которой имеют только аутентифицированные пользователи.

SignInScreen — это виджет из пакета FlutterFire UI. Это будет в центре внимания следующего шага этой кодовой лаборатории. Когда вы запустите приложение на этом этапе, вы должны увидеть пустой экран входа.

5. Экран входа в систему

Виджет SignInScreen , предоставляемый FlutterFire UI, добавляет следующие функции:

  • Позволяет пользователям входить в систему
  • Если пользователи забыли свой пароль, они могут нажать «Забыли пароль?» и перейти к форме для сброса пароля.
  • Если пользователь еще не зарегистрирован, он может нажать «Зарегистрироваться» и перейти на другую форму, позволяющую ему зарегистрироваться.

Опять же, для этого требуется всего пара строк кода. Вспомним код в виджете AuthGate :

lib/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, required this.clientId});

  final String clientId;

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

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

Виджет SignInScreen и его аргумент providers — это единственный код, необходимый для получения всех вышеупомянутых функций. Теперь вы должны увидеть экран входа с текстовыми полями «email» и «password», а также кнопкой «Sign In».

Хотя он функционален, ему не хватает стиля. Виджет предоставляет параметры для настройки внешнего вида экрана входа. Например, вы можете добавить логотип своей компании.

Настройте экран входа

headerBuilder

Используя аргумент SignInScreen.headerBuilder , вы можете добавить любые виджеты над формой входа. Этот виджет отображается только на узких экранах, таких как мобильные устройства. На широких экранах вы можете использовать SignInScreen.sideBuilder , который обсуждается далее в этой кодовой лаборатории.

Обновите файл lib/auth_gate.dart , добавив следующий код:

lib/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, required this.clientId});

  final String clientId;

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

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

The headerBuilder argument requires a function of the type HeaderBuilder, which
is defined in the FlutterFire UI package.

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

Поскольку это обратный вызов, он предоставляет значения, которые вы можете использовать, такие как BuildContext и BoxConstraints , и требует, чтобы вы вернули виджет. Какой бы виджет вы ни вернули, он отображается в верхней части экрана. В этом примере новый код добавляет изображение в верхнюю часть экрана. Теперь ваше приложение должно выглядеть так.

73d7548d91bbd2ab.png

Конструктор субтитров

Экран входа предоставляет три дополнительных параметра, которые позволяют настраивать экран: subtitleBuilder , footerBuilder и sideBuilder .

subtitleBuilder немного отличается тем, что аргументы обратного вызова включают действие, которое имеет тип AuthAction . AuthAction — это перечисление, которое можно использовать для определения того, является ли экран, на котором находится пользователь, экраном «входа» или экраном «регистрации».

Обновите код в auth_gate.dart для использования subtitleBuilder .

lib/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, required this.clientId});

  final String clientId;

  @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'),
                ),
              );
            },
            subtitleBuilder: (context, action) {                     // Add from here...
              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!'),
              );
            },                                                       // To here.
          );
        }

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

Аргумент footerBuilder такой же, как и subtitleBuilder. Он не раскрывает BoxConstraints или shrinkOffset , поскольку предназначен для текста, а не изображений. Конечно, вы можете добавить любой виджет, который захотите.

Добавьте нижний колонтитул на экран входа с помощью этого кода.

lib/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, required this.clientId});

  final String clientId;

  @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'),
                ),
              );
            },
            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) {                       // Add from here...
              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),
                ),
              );
            },                                                       // To here.
          );
        }

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

Боковой строитель

Аргумент SignInScreen.sidebuilder принимает обратный вызов, и на этот раз аргументами этого обратного вызова являются BuildContext и double shrinkOffset . Виджет, который возвращает sideBuilder , будет отображаться слева от формы входа и только на широких экранах. Фактически это означает, что виджет будет отображаться только в настольных и веб-приложениях.

Внутренне FlutterFire UI использует контрольную точку для определения того, следует ли отображать содержимое заголовка (на высоких экранах, например, мобильных) или боковое содержимое (на широких экранах, настольных компьютерах или веб-сайтах). В частности, если ширина экрана превышает 800 пикселей, отображается боковое содержимое конструктора, а содержимое заголовка — нет. Если ширина экрана меньше 800 пикселей, то верно обратное.

Обновите код в auth_gate.dart, чтобы добавить виджеты sideBuilder .

lib/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, required this.clientId});

  final String clientId;

  @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'),
                ),
              );
            },
            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();
      },
    );
  }
}

Теперь при увеличении ширины окна ваше приложение должно выглядеть следующим образом (если вы используете Flutter Web или MacOS).

8dc60b4e5d7dd2d0.png

Создать пользователя

На этом этапе весь код для этого экрана готов. Однако перед тем, как вы сможете войти в систему, вам нужно создать пользователя. Вы можете сделать это с помощью экрана «Регистрация» или создать пользователя в консоли Firebase.

Чтобы использовать консоль:

  1. Перейдите в таблицу "Users" в консоли Firebase . Выберите "flutterfire-ui-codelab" или другой проект, если вы использовали другое имя. Вы увидите эту таблицу: f038fd9a58ed60d9.png
  2. Нажмите кнопку «Добавить пользователя». 2d78390d4c5dbbfa.png
  3. Введите адрес электронной почты и пароль для нового пользователя. Это может быть поддельный адрес электронной почты и пароль, как я ввел на изображении ниже. Это сработает, но функция «Забыли пароль» не будет работать, если вы используете поддельный адрес электронной почты. 62ba0feb33d54add.png
  4. Нажмите «Добавить пользователя». 32b236b3ef94d4c7.png

Теперь вы можете вернуться в свое приложение Flutter и войти в систему пользователя, используя страницу входа. Ваше приложение должно выглядеть следующим образом:

dd43d260537f3b1a.png

6. Экран профиля

Пользовательский интерфейс FlutterFire также предоставляет виджет ProfileScreen , который, опять же, предоставляет вам массу функциональных возможностей в нескольких строках кода.

Добавить виджет ProfileScreen

Перейдите к файлу home.dart в текстовом редакторе. Обновите его следующим кодом:

lib/home.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: [
            SizedBox(width: 250, child: Image.asset('assets/dash.png')),
            Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Новый код, который следует отметить, — это обратный вызов, переданный методу IconButton.isPressed . При нажатии этого IconButton ваше приложение создает новый анонимный маршрут и переходит к нему. Этот маршрут отобразит виджет ProfileScreen , который возвращается из обратного вызова MaterialPageRoute.builder .

Перезагрузите приложение и нажмите на значок в правом верхнем углу (на панели приложения), после чего отобразится следующая страница:

36487fc4ab4f26a7.png

Это стандартный пользовательский интерфейс, предоставляемый страницей FlutterFire UI. Все кнопки и текстовые поля подключены к Firebase Auth и работают из коробки. Например, вы можете ввести имя в текстовое поле "Name", и FlutterFire UI вызовет метод FirebaseAuth.instance.currentUser?.updateDisplayName , который сохранит это имя в Firebase.

Выход

Прямо сейчас, если вы нажмете кнопку «Выйти», приложение не изменится. Оно выполнит выход, но вы не будете перенаправлены обратно к виджету AuthGate. Чтобы реализовать это, используйте параметр ProfileScreen.actions.

Сначала обновите код в home.dart.

lib/home.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: [
            SizedBox(width: 250, child: Image.asset('assets/dash.png')),
            Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Теперь, когда вы создаете экземпляр ProfileScreen , вы также передаете ему список действий в аргумент ProfileScreen.actions . Эти действия имеют тип FlutterFireUiAction . Существует много различных классов, которые являются подтипами FlutterFireUiAction , и в целом вы используете их, чтобы сообщить своему приложению, что нужно реагировать на различные изменения состояния аутентификации. SignedOutAction вызывает функцию обратного вызова, которую вы ему даете, когда состояние аутентификации Firebase изменяется на currentUser, равный null.

Добавляя обратный вызов, который вызывает Navigator.of(context).pop() при срабатывании SignedOutAction , приложение перейдет на предыдущую страницу. В этом примере приложения есть только один постоянный маршрут, который показывает экран входа, если пользователь не вошел в систему, и домашнюю страницу, если пользователь есть. Поскольку это происходит, когда пользователь выходит из системы, приложение отобразит экран входа.

Настройте страницу профиля

Подобно экрану входа в систему, страницу профиля можно настраивать. Во-первых, наша текущая страница не имеет возможности вернуться на домашнюю страницу, как только пользователь оказывается на странице профиля. Исправьте это, добавив виджету ProfileScreen AppBar.

lib/home.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: [
            SizedBox(width: 250, child: Image.asset('assets/dash.png')),
            Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Аргумент ProfileScreen.appBar принимает виджет AppBar из пакета Flutter Material, поэтому его можно рассматривать как любой другой AppBar , который вы создали и передали в Scaffold . В этом примере сохраняется функциональность по умолчанию для автоматического добавления кнопки «назад», а экран теперь имеет заголовок.

Добавить детей на экран профиля

Виджет ProfileScreen также имеет необязательный аргумент с именем children. Этот аргумент принимает список виджетов, и эти виджеты будут размещены вертикально внутри виджета Column , который уже используется внутренне для построения ProfileScreen . Этот виджет Column в методе сборки ProfileScreen разместит переданные вами дочерние элементы над кнопкой «Выйти».

Обновите код в home.dart , чтобы отобразить здесь логотип компании, как на экране входа в систему.

lib/home.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: [
            SizedBox(width: 250, child: Image.asset('assets/dash.png')),
            Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Перезагрузите приложение, и вы увидите это на экране:

ebe5792b765dbf87.png

7. Мультиплатформенный вход с помощью Google Auth

Пользовательский интерфейс FlutterFire также предоставляет виджеты и функции для аутентификации у сторонних поставщиков, таких как Google, Twitter, Facebook, Apple и GitHub.

Для интеграции с аутентификацией Google установите официальный плагин firebase_ui_oauth_google и его зависимости, которые будут обрабатывать собственный поток аутентификации. В терминале перейдите в корень вашего проекта Flutter и введите следующую команду:

flutter pub add google_sign_in firebase_ui_oauth_google

Включить поставщика входа Google

Далее включите провайдера Google в консоли Firebase :

  1. Перейдите на экран «Поставщики аутентификации» в консоли.
  2. Нажмите «Добавить нового поставщика». 8286fb28be94bf30.png
  3. Выберите «Google». c4e28e6f4974be7f.png
  4. Переключите переключатель «Включить» и нажмите «Сохранить». e74ff86990763826.png
  5. Если появится модальное окно с информацией о загрузке файлов конфигурации, нажмите «Готово».
  6. Убедитесь, что поставщик входа Google добавлен. 5329ce0543c90d95.png

Добавить кнопку входа в Google

При включенном входе Google добавьте виджет, необходимый для отображения стилизованной кнопки входа Google на экране входа. Перейдите к файлу auth_gate.dart и обновите код следующим образом:

lib/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';  // Add this import
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
  const AuthGate({super.key, required this.clientId});

  final String clientId;

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

Единственный новый код здесь — это добавление GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") в конфигурацию виджета SignInScreen .

После этого перезагрузите приложение, и вы увидите кнопку входа в Google.

aca71a46a011bfb5.png

Настроить кнопку входа

Кнопка не работает без дополнительной настройки. Если вы разрабатываете с Flutter Web, это единственный шаг, который вам нужно добавить, чтобы это заработало. Другие платформы требуют дополнительных шагов, которые обсуждаются немного позже.

  1. Перейдите на страницу «Поставщики аутентификации» в консоли Firebase .
  2. Нажмите на поставщика Google. 9b3a325c5eca6e49.png
  3. Нажмите на панель расширения «Конфигурация Web SDK».
  4. Скопируйте значение из «Идентификатора веб-клиента». 711a79f0d931c60f.png
  5. Вернитесь в текстовый редактор и обновите экземпляр GoogleProvider в файле auth_gate.dart , передав этот идентификатор именованному параметру clientId .
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

После ввода идентификатора веб-клиента перезагрузите приложение. При нажатии кнопки «Войти через Google» появится новое окно, если вы используете веб, которое проведет вас через процесс входа в Google. Изначально это выглядит так:

14e73e3c9de704bb.png

Настроить iOS

Чтобы это работало на iOS, необходимо выполнить дополнительную настройку.

  1. Перейдите на экран Project Settings в консоли Firebase . Там будет карточка со списком ваших приложений Firebase, которая выглядит следующим образом: fefa674acbf213cc.png
  2. Выберите iOS. Обратите внимание, что имя вашего приложения будет отличаться от показанного на снимке экрана. Там, где на снимке экрана написано «complete», на вашем будет написано «start», если вы использовали проект flutter-codelabs/firebase-auth-flutterfire-ui/start для выполнения этой кодовой лабораторной работы.
  3. Нажмите кнопку с надписью GoogleServices-Info.plist чтобы загрузить необходимый файл конфигурации. f89b3192871dfbe3.png
  4. Перетащите загруженный файл в каталог /ios/Runner вашего проекта Flutter.
  5. Откройте Xcode, выполнив следующую команду терминала из корня вашего проекта: open ios/Runner.xcworkspace
  6. Щелкните правой кнопкой мыши по каталогу Runner и выберите «Добавить файлы в «Runner»». 858986063a4c5201.png
  7. Выберите GoogleService-Info.plist в файловом менеджере.
  8. Вернитесь в текстовый редактор (не Xcode) и добавьте атрибуты CFBundleURLTypes , указанные ниже, в файл 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 -->
    
  9. Вам необходимо заменить GoogleProvider.clientId , который вы добавили в веб-настройке, на Client Id, связанный с вашим клиентским ID Firebase iOS. Во-первых, вы можете найти этот ID в файле firebase_options.dart как часть константы iOS . Скопируйте значение, переданное в iOSClientId .
    static const FirebaseOptions ios = FirebaseOptions(
      apiKey: 'YOUR API KEY',
      appId: 'YOUR APP ID',
      messagingSenderId: '',
      projectId: 'PROJECT_ID',
      storageBucket: 'PROJECT_ID.firebasestorage.app',
      iosClientId: 'IOS CLIENT ID', // Find your iOS client Id here.
      iosBundleId: 'com.example.BUNDLE',
    );
    
  10. Вставьте это значение в переменную clientId в файле lib/main.dart .

lib/main.dart

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

import 'app.dart';
import 'firebase_options.dart';

const clientId = 'YOUR_CLIENT_ID'; // Replace this value with your Client ID.

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

  runApp(const MyApp(clientId: clientId));
}

Если ваше приложение Flutter уже запущено в iOS, вам придется полностью его закрыть и затем перезапустить приложение. В противном случае запустите приложение в iOS.

8. Поздравляю!

Вы завершили Firebase Auth UI для Flutter codelab. Вы можете найти завершенный код для этой Codelab в каталоге firebase-auth-flutterfire-ui/complete на GitHub .

Что мы рассмотрели

  • Настройка приложения Flutter для использования Firebase
  • Настройка проекта Firebase в консоли Firebase
  • Интерфейс командной строки FlutterFire
  • Firebase CLI
  • Использование аутентификации Firebase
  • Использование FlutterFire UI для обработки аутентификации Firebase в вашем приложении Flutter

Следующие шаги

Узнать больше

Спарки здесь, чтобы отпраздновать вместе с вами!

2a0ad195769368b1.gif