颤动的firebase登录问题

Posted

技术标签:

【中文标题】颤动的firebase登录问题【英文标题】:issue with flutter firebase login 【发布时间】:2021-03-05 00:43:23 【问题描述】:

我最近在我的应用程序上使用登录/注册模块进行了操作,但有 2 件事无法正常工作:

首先当我注册没问题时,我可以在我的 Firebase 控制台中看到该应用正在创建一个新用户,这很好。但是,当我尝试使用不存在的用户登录时,它仍然会让我转到主页。 不知道如何进行持久登录,例如在关闭应用程序然后重新启动应用程序时登录和注册的人应该能够保持登录状态,然后在需要时注销。

有人可以帮忙吗??

我把代码留在这里:

主要

import 'package:flutter/material.dart';
import 'package:sport_app/auth_screen.dart';
import 'package:sport_app/home_screen.dart';
import 'package:sport_app/intro_screen.dart';


void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
        inputDecorationTheme: InputDecorationTheme(
          filled: true,
          fillColor: Color(0xfff2f9fe),
          enabledBorder: OutlineInputBorder(
            borderSide: BorderSide(color: Colors.grey[200]),
            borderRadius: BorderRadius.circular(25),
          ),
          focusedBorder: OutlineInputBorder(
            borderSide: BorderSide(color: Colors.grey[200]),
            borderRadius: BorderRadius.circular(25),
          ),
          disabledBorder: OutlineInputBorder(
            borderSide: BorderSide(color: Colors.grey[200]),
            borderRadius: BorderRadius.circular(25),
          ),
        ),
      ),
      home: IntroScreen(),
      routes: 
        'intro': (context) => IntroScreen(),
        'home': (context) => HomeScreen(),
        'login': (context) => AuthScreen(authType: AuthType.login),
        'register': (context) => AuthScreen(authType: AuthType.register),
      ,
    );
  

AUTH_PAGE

import 'package:flutter/material.dart';
import 'package:sport_app/auth_screen.dart';
import 'package:sport_app/auth.dart';
import 'package:sport_app/original_button.dart';


class AuthForm extends StatefulWidget 
  final AuthType authType;

  const AuthForm(Key key, @required this.authType) : super(key: key);

  @override
  _AuthFormState createState() => _AuthFormState();


class _AuthFormState extends State<AuthForm> 
  final _formKey = GlobalKey<FormState>();
  String _email = '', _password = '';
  AuthBase authBase = AuthBase();

  @override
  Widget build(BuildContext context) 
    return Form(
      key: _formKey,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 20),
        child: Column(
          children: <Widget>[
            TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter your email',
                hintText: 'ex: test@gmail.com',
              ),
              onChanged: (value) 
                _email = value;
              ,
              validator: (value) =>
              value.isEmpty ? 'You must enter a valid email' : null,
            ),
            SizedBox(height: 10),
            TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter your password',
              ),
              obscureText: true,
              onChanged: (value) 
                _password = value;
              ,
              validator: (value) => value.length <= 6
                  ? 'Your password must be larger than 6 characters'
                  : null,
            ),
            SizedBox(height: 20),
            OriginalButton(
              text: widget.authType == AuthType.login ? 'Login' : 'Register',
              color: Colors.lightBlue,
              textColor: Colors.white,
              onPressed: () async 
                if (_formKey.currentState.validate()) 
                  if (widget.authType == AuthType.login) 
                    await authBase.loginWithEmailAndPassword(_email, _password);
                    Navigator.of(context).pushReplacementNamed('home');
                   else 
                    await authBase.registerWithEmailAndPassword(_email, _password);
                    Navigator.of(context).pushReplacementNamed('home');
                  
//                  print(_email);
//                  print(_password);
                
              ,
            ),
            SizedBox(height: 6),
            FlatButton(
              onPressed: () 
                if (widget.authType == AuthType.login) 
                  Navigator.of(context).pushReplacementNamed('register');
                  print(widget.authType);
                 else 
                  Navigator.of(context).pushReplacementNamed('login');
                
              ,
              child: Text(
                widget.authType == AuthType.login
                    ? 'Don\'t have an account?'
                    : 'Already have an account?',
                style: TextStyle(fontSize: 18, color: Colors.black54),
              ),
            ),
          ],
        ),
      ),
    );
  

AUTHBASE

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

class User 
  final String uid;

  User(@required this.uid);


class AuthBase 
  User _userFromFirebase(FirebaseUser user) 
    return user != null ? User(uid: user.uid) : null;
  

  Future<void> registerWithEmailAndPassword(
      String email, String password) async 
    try 
      final authResult = await FirebaseAuth.instance
          .createUserWithEmailAndPassword(email: email, password: password);
      return _userFromFirebase(authResult.user);
     catch (e) 
      print(e.toString());
      return null;
    
  

  Future<void> loginWithEmailAndPassword(String email, String password) async 
    try 
      final authResult = await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: email, password: password);
      return _userFromFirebase(authResult.user);
     catch (e) 
      print(e.toString());
      return null;
    
  

  Future<void> logout() async 
    await FirebaseAuth.instance.signOut();
  

【问题讨论】:

如果我的回答对你有帮助,那就把它标记为答案:) 【参考方案1】:

更新

您只需导航到主页,即使登录没有成功完成,因为没有条件逻辑。只在您的 authBase 类中进行导航,那么您应该没问题。

您需要先导入 FirebaseAuthException,然后才能使用它。那么,你

Future<bool> loginWithEmailAndPassword(String email, String password) async 
    try 
      final authResult = await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: email, password: password);
      if(authResult.user != null)  Navigator.of(context).pushReplacementNamed('home'); 
     on FirebaseAuthException catch (e) 
      print(e.toString());
      if(e.code == 'wrong-password')  Scaffold.of(context).showSnackBar(SnackBar(
      content: Text("Wrong Password"),
    ));  
      else if (e.code == 'user-not-found')  Scaffold.of(context).showSnackBar(SnackBar(
      content: Text("User not found"),
    )); 
      else if (e.code == 'invalid-email')  Scaffold.of(context).showSnackBar(SnackBar(
      content: Text("Invalid E-Mail"),
    )); 
      return false;
    
  

并删除将您的小部件代码更改为:

if (_formKey.currentState.validate()) 
  if (widget.authType == AuthType.login) 
    await authBase.loginWithEmailAndPassword(_email, _password);
   else 
    await authBase.registerWithEmailAndPassword(_email, _password);
  

第二个问题: 您可以尝试在第一次登录后将登录凭据存储在存储中(用户 flutter_secure_storage 包进行加密),然后在应用启动时检索它以执行上述登录

这是您应该用来存储凭据的包的链接


flutter_secure_storage

【讨论】:

这很有帮助,谢谢!我对编码很陌生,我正在学习很多东西以使事情顺利进行。我理解了你上面提到的一半 bool 函数(虽然不知道在哪里写),我的意思是,我想我只需要导航,因为我正在导航到应用程序中的任何页面,所以我想没关系。不过,我不知道如何处理登录失败...对于第二个问题,我实际上对此一无所知,因此,如果您有链接或以前有关堆栈溢出的帖子,那将有很大帮助!谢谢!! @PasqualeCapuano 我已经更新了我的答案,如果您认为这有帮助,请将其标记为答案 我知道 OriginalButton 的 onPressed 函数存在问题,但我尝试将 'home' 更改为 'intro' 并且仍然将我带到主页。我还创建了一个新页面并尝试导航到 materialpageroute,但仍然无法正常工作。 p.s.我肯定会将答案标记为没有问题,但我想解决这个问题并理解不仅仅是复制和粘贴一些代码。 您是否将登录函数更改为 Future 并返回一个表示登录状态的布尔值(true、false)? 嗯,不,所以我绝对什么都不懂?请帮忙!我正在用头撞墙?

以上是关于颤动的firebase登录问题的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 身份验证颤动

颤动的firebase身份验证提供者未通知

使用refreshToken颤动firebase自动刷新用户会话

颤动中特定设备的Firebase消息通知

我在颤动时无法捕捉到 Firebase Auth 的异常

在颤动中按下注销按钮后如何重定向到登录页面