Flutter Firebase身份验证教程

在Flutter Firebase身份验证的这篇文章中,我们将了解如何使用Firebase的flutter插件向我们的Firebase应用程序验证用户身份。

如果您不熟悉颤动,建议您先阅读此内容,然后再继续。 它将为您提供有关抖动的基本概念,并帮助您完成本教程。

https://ayusch.com/getting-started-with-flutter-app-development/

我们将创建一个具有登录屏幕和主页的基本应用程序。 它可以让用户登录注销应用程序。 我们还将具有允许用户注册到我们的Firebase应用程序的功能。

这是应用程序的基本流程:

Flutter Firebase身份验证教程_第1张图片

所以,让我们开始吧!

创建Flutter应用程序

转到Android Studio并通过单击“ 新建”->“ Flutter项目”并遵循从那里开始的向导来创建Flutter应用程序。

删除默认计数器应用程序的代码,并添加以下行:

 import 'package:flutter/material.dart' ;  import 'package:flutter_firebase_auth/root_page.dart' ;  import 'LoginSignupPage.dart' ;  import 'authentication.dart' ;  void main() => runApp(MyApp());  MyApp class extends StatelessWidget { 
   // This widget is the root of your application. 
   @override 
   Widget build(BuildContext context) { 
     return MaterialApp( 
       title: 'Flutter Authentication AndroidVille' , 
       theme: ThemeData( 
         primarySwatch: Colors.blue, 
       ), 
       home: RootPage( 
         auth: new Auth(), 
       ), 
     ); 
   }  } 

我们将很快创建RootPage。

注意 :请记住不要使用AndroidX工件。 Firebase的Flutter插件包含一些AndroidX不支持的注释。 在升级之前,我们不要使用AndroidX。

添加依赖项

我们需要在android / flutter中添加一些依赖关系,以便Flutter使用Firebase身份验证。

首先,将其添加到项目级别的build.gradle文件。 对于扑扑的项目,这可以在android / build.gradle中找到

 classpath 'com.google.gms:google-services:4.3.2' 

接下来,我们需要将google-services插件应用于应用程序级别build.gradle 这可以在android / app / build.gradle中找到。 将此行添加到文件末尾。

 apply plugin: 'com.google.gms.google-services' 

最后,我们需要为flutter添加firebase插件。 打开pubspec.yaml并在依赖项下添加以下行:

 firebase_auth: ^ 0.6 . 6 

创建Flutter Firebase身份验证服务

接下来,我们需要为flutter的firebase登录系统创建身份验证服务。 所有页面(或android中的活动)都将使用它与Firebase进行通信。

创建一个新的dart文件,名称为: authentication.dart

我们将首先添加一个抽象的BaseAuth类,该类将由Auth类实现。 这包含登录,注册,获取用户信息和注销用户的基本方法。

 import 'dart:async' ;  import 'package:firebase_auth/firebase_auth.dart' ;  abstract class BaseAuth { 
   Future signIn(String email, String password); 
   Future signUp(String email, String password); 
   Future getCurrentUser(); 
   Future< void > signOut();  } 

在同一文件中,创建一个名为Auth的类,并实现BaseAuth类。 覆盖所有方法,如下所示:

 import 'dart:async' ;  import 'package:firebase_auth/firebase_auth.dart' ;  abstract class BaseAuth { 
   Future signIn(String email, String password); 
   Future signUp(String email, String password); 
   Future getCurrentUser(); 
   Future< void > signOut();  }  Auth class implements BaseAuth { 
   final FirebaseAuth _firebaseAuth = FirebaseAuth.instance; 
   Future signIn(String email, String password) async { 
     FirebaseUser user = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password); 
     return user.uid; 
   } 
   Future signUp(String email, String password) async { 
     FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(email: email, password: password); 
     return user.uid; 
   } 
   Future getCurrentUser() async { 
     FirebaseUser user = await _firebaseAuth.currentUser(); 
     return user; 
   } 
   Future< void > signOut() async { 
     return _firebaseAuth.signOut(); 
   }  } 

我们在这里所做的是创建一个全局Firebase实例,并使用它来为用户执行登录/注销。

创建根页面

我们需要创建一个根目录来标识用户是否已登录。 如果用户已登录 ,我们会将其定向到主页,否则将向他显示登录/注册屏幕。

创建一个root_page.dart ,如下所示:

 import 'package:flutter/material.dart' ;  import 'authentication.dart' ;  import 'LoginSignupPage.dart' ;  import 'home_page.dart' ;  RootPage class extends StatefulWidget { 
   RootPage({ this .auth}); 
   final BaseAuth auth; 
   @override 
   State createState() => new _RootPageState();  }  enum AuthStatus { 
   NOT_DETERMINED, 
   LOGGED_OUT, 
   LOGGED_IN,  }  _RootPageState class extends State { 
   AuthStatus authStatus = AuthStatus.NOT_DETERMINED; 
   String _userId = "" ; 
   @override 
   void initState() { 
     super .initState(); 
     widget.auth.getCurrentUser().then((user) { 
       setState(() { 
         if (user != null ) { 
           _userId = user?.uid; 
         } 
         authStatus = 
             user?.uid == null ? AuthStatus.LOGGED_OUT : AuthStatus.LOGGED_IN; ? AuthStatus.LOGGED_OUT : AuthStatus.LOGGED_IN; 
       }); 
     }); 
   } 
   void _onLoggedIn() { 
     widget.auth.getCurrentUser().then((user) { 
       setState(() { 
         _userId = user.uid.toString(); 
       }); 
     }); 
     setState(() { 
       authStatus = AuthStatus.LOGGED_IN; 
     }); 
   } 
   void _onSignedOut() { 
     setState(() { 
       authStatus = AuthStatus.LOGGED_OUT; 
       _userId = "" ; 
     }); 
   } 
   Widget progressScreenWidget() { 
     return Scaffold( 
       body: Container( 
         alignment: Alignment.center, 
         child: CircularProgressIndicator(), 
       ), 
     ); 
   } 
   @override 
   Widget build(BuildContext context) { 
     switch (authStatus) { 
       case AuthStatus.NOT_DETERMINED: 
         return progressScreenWidget(); 
         break ; 
       case AuthStatus.LOGGED_OUT: 
         return new LoginSignupPage( 
           auth: widget.auth, 
           onSignedIn: _onLoggedIn, 
         ); 
         break ; 
       case AuthStatus.LOGGED_IN: 
         if (_userId.length > 0 && _userId != null ) { 
           return new HomePage( 
             userId: _userId, 
             auth: widget.auth, 
             onSignedOut: _onSignedOut, 
           ); 
         } else 
           return progressScreenWidget(); 
         break ; 
       default : 
         return progressScreenWidget(); 
     } 
   }  } 

这里要注意的主要是构建方法。 对于不同的用户状态,我们返回不同的小部件。 我们将很快创建LoginSignupPageHomePage

为了显示进度条,我们使用Flutter提供的默认CircularProgressIndicator

另外,请注意,我们在构造函数中传递了auth对象。 这是从main.dart传递的

创建LoginSignupPage

这是最重要的部分,我们将创建一个登录/注册表单。 我们将基于formMode区分这些形式。

我们总共有6个小部件:

  1. 电子邮件字段。
  2. 密码字段。
  3. 登录按钮
  4. 在登录和注册表格之间切换的按钮。
  5. 进度条
  6. 错误消息小部件。

这是LoginSignupPage的代码:

 import 'package:flutter/material.dart' ;  import 'package:firebase_auth/firebase_auth.dart' ;  import 'authentication.dart' ;  class LoginSignupPage extends StatefulWidget { 
   .auth, LoginSignupPage({ this .auth, this .onSignedIn}); 
   final BaseAuth auth; 
   final VoidCallback onSignedIn; 
   @override 
   State createState() => new _LoginSignupPageState();  }  enum FormMode { LOGIN, SIGNUP }  class _LoginSignupPageState extends State { _LoginSignupPageState State { 
   final _formKey = new GlobalKey(); 
   String _email; 
   String _password; 
   String _errorMessage = "" ; 
   // this will be used to identify the form to show 
   FormMode _formMode = FormMode.LOGIN; 
   bool _isIos = false ; 
   bool _isLoading = false ; 
   @override 
   Widget build(BuildContext context) { 
     return new Scaffold( 
       appBar: new AppBar( 
         title: new Text( "Flutter login demo" ), 
       ), 
       body: Column( 
         children: [ 
           formWidget(), 
           loginButtonWidget(), 
           secondaryButton(), 
           errorWidget(), 
           progressWidget() 
         ], 
       ), 
     ); 
   } 
   Widget progressWidget() { 
     if (_isLoading) { 
       return Center(child: CircularProgressIndicator()); 
     } 
     return Container( 
       height: 0.0 , 
       width: 0.0 , 
     ); 
   } 
   Widget formWidget() { 
     return Form( 
       key: _formKey, 
       child: Column( 
         children: [ 
           _emailWidget(), 
           _passwordWidget(), 
         ], 
       ), 
     ); 
   } 
   Widget _emailWidget() { 
     return Padding( 
       padding: const EdgeInsets.fromLTRB( 0.0 , 100.0 , 0.0 , 0.0 ), 
       child: TextFormField( 
         maxLines: 1 , 
         keyboardType: TextInputType.emailAddress, 
         autofocus: false , 
         decoration: new InputDecoration( 
             hintText: 'Enter Email' , 
             icon: new Icon( 
               Icons.mail, 
               color: Colors.grey, 
             )), 
         validator: (value) => value.isEmpty ? 'Email cannot be empty' : null , 
         onSaved: (value) => _email = value.trim(), 
       ), 
     ); 
   } 
   Widget _passwordWidget() { 
     return Padding( 
       padding: const EdgeInsets.fromLTRB( 0.0 , 15.0 , 0.0 , 0.0 ), 
       child: new TextFormField( 
         maxLines: 1 , 
         obscureText: true , 
         autofocus: false , 
         decoration: new InputDecoration( 
             hintText: 'Password' , 
             icon: new Icon( 
               Icons.lock, 
               color: Colors.grey, 
             )), 
         validator: (value) => value.isEmpty ? 'Password cannot be empty' : null , 
         onSaved: (value) => _password = value.trim(), 
       ), 
     ); 
   } 
   Widget loginButtonWidget() { 
     return new Padding( 
         padding: EdgeInsets.fromLTRB( 0.0 , 45.0 , 0.0 , 0.0 ), 
         child: new MaterialButton( 
           elevation: 5.0 , 
           minWidth: 200.0 , 
           height: 42.0 , 
           color: Colors.blue, 
           child: _formMode == FormMode.LOGIN 
               ? new Text( 'Login' , 
                   style: new TextStyle(fontSize: 20.0 , color: Colors.white)) 
               : new Text( 'Create account' , 
                   style: new TextStyle(fontSize: 20.0 , color: Colors.white)), 
           onPressed: _validateAndSubmit, 
         )); 
   } 
   Widget secondaryButton() { 
     return new FlatButton( 
       child: _formMode == FormMode.LOGIN 
           ? new Text( 'Create an account' , 
               style: new TextStyle(fontSize: 18.0 , fontWeight: FontWeight.w300)) 
           : new Text( 'Have an account? Sign in' , 
               style: 
                   new TextStyle(fontSize: 18.0 , fontWeight: FontWeight.w300)), 
       onPressed: _formMode == FormMode.LOGIN ? showSignupForm : showLoginForm, 
     ); 
   } 
   void showSignupForm() { 
     _formKey.currentState.reset(); 
     _errorMessage = "" ; 
     setState(() { 
       _formMode = FormMode.SIGNUP; 
     }); 
   } 
   void showLoginForm() { 
     _formKey.currentState.reset(); 
     _errorMessage = "" ; 
     setState(() { 
       _formMode = FormMode.LOGIN; 
     }); 
   } 
   Widget errorWidget() { 
     if (_errorMessage.length > 0 && _errorMessage != null ) { 
       return new Text( 
         _errorMessage, 
         style: TextStyle( 
             fontSize: 13.0 , 
             color: Colors.red, 
             height: 1.0 , 
             fontWeight: FontWeight.w300), 
       ); 
     } else { 
       return new Container( 
         height: 0.0 , 
       ); 
     } 
   } 
   bool _validateAndSave() { 
     final form = _formKey.currentState; 
     if (form.validate()) { 
       form.save(); 
       return true ; 
     } 
     return false ; 
   } 
   _validateAndSubmit() async { 
     setState(() { 
       _errorMessage = "" ; 
       _isLoading = true ; 
     }); 
     if (_validateAndSave()) { 
       String userId = "" ; 
       try { 
         if (_formMode == FormMode.LOGIN) { 
           userId = await widget.auth.signIn(_email, _password); 
         } else { 
           userId = await widget.auth.signUp(_email, _password); 
         } 
         setState(() { 
           _isLoading = false ; 
         }); 
         if (userId.length > 0 && userId != null ) { 
           widget.onSignedIn(); 
         } 
       } catch (e) { 
         setState(() { 
           _isLoading = false ; 
           if (_isIos) { 
             _errorMessage = e.details; 
           } else 
             _errorMessage = e.message; 
         }); 
       } 
     } else { 
       setState(() { 
         _isLoading = false ; 
       }); 
     } 
   }  } 

注意方法validateAndSubmit() ,当人们按下登录按钮时会调用该方法。 首先,我们将加载的初始状态设置为true和空错误。

同样,我建议您查阅此文章知道的setState方法做。

之后,我们验证表单,然后在formMode的基础上,登录用户或注册用户。 在这两种情况下,我们都将获得userId。

最后,我们在小部件上调用onSignedIn方法。 此方法是VoidCallback ,由根页在LoginSignupPage的构造函数中提供。

最终,根页面调用它的onLoggedIn方法,该方法设置userId并最终调用setState() 这将导致重建,然后我们转到主屏幕。

这样就完成了LoginSignupPage 现在,是时候在我们的主页中添加注销功能。

要完成此Flutter firebase身份验证教程,我们必须添加注销功能。 注销仅表示设置空用户ID并重定向到LoginSignupPage。

这是HomePage的代码:

 import 'package:flutter/material.dart' ;  import 'authentication.dart' ;  class HomePage extends StatefulWidget { 
   HomePage({Key key, this .auth, this .userId, this .onSignedOut}) 
       : super (key: key); 
   final BaseAuth auth; 
   final VoidCallback onSignedOut; 
   final String userId; 
   @override 
   State createState() => new _HomePageState();  }  _HomePageState class extends State { 
   _signOut() async { 
     try { 
       await widget.auth.signOut(); 
       widget.onSignedOut(); 
     } catch (e) { 
       print(e); 
     } 
   } 
   @override 
   Widget build(BuildContext context) { 
     return new Scaffold( 
       appBar: new AppBar( 
         title: new Text( 'Flutter login demo' ), 
         actions: [ 
           new FlatButton( 
               child: new Text( 'Logout' , 
                   style: new TextStyle(fontSize: 17.0 , color: Colors.white)), 
               onPressed: _signOut) 
         ], 
       ), 
       body: Center( 
         child: Text( "hello" ), 
       ), 
     ); 
   }  } 

我们将退出按钮保留在应用程序栏中。 当用户点击,我们调用由root_page提供的onSignedOut方法。

根页面简单地设置用户LoggedOut用户id空字符串authState。

最终结果如下所示:

Flutter Firebase身份验证教程_第2张图片

结论

希望您觉得本文有用。 如果您愿意,请在下面的评论部分中告诉我,我很乐意写更多这样的概念文章。

您可以在以下位置找到本文的完整代码: https : //github.com/Ayusch/Flutter-Firebase-Authentication

如果您有任何疑问,请在下面的评论中告诉我,我们将竭诚为您服务!

翻译自: https://www.javacodegeeks.com/2019/09/flutter-firebase-authentication-tutorial.html

你可能感兴趣的:(Flutter Firebase身份验证教程)