Flutter Firebase无法持续进行用户身份验证

qcbq4gxm  于 2023-03-19  发布在  Flutter
关注(0)|答案(2)|浏览(155)

我正在Flutter中创建一个使用Firebase Google身份验证的应用程序。我可以登录到该应用程序,但当我关闭该应用程序时,身份验证被删除,需要我重新登录。
这是我的登录屏幕,“登录Google”按钮将触发onPressed()in _signInButton()。

import 'package:flutter/material.dart';
import 'package:auth_screen/sign_in.dart';
import 'package:auth_screen/homepage.dart';

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.white,
        child: Center(
          child: Column(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Image(image: AssetImage("assets/thelogo.jpg"), height: 200.0),
              SizedBox(height: 25),
             _signInButton(),
            ],
          ),
        ),
      ),
    );
  }

  Widget _signInButton() {
    return OutlineButton(
      splashColor: Colors.grey,
      onPressed: () {
        signInWithGoogle().whenComplete(() {
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (context) {
                return MyHomePage();
              },
            ),
          );
      });
      },
     shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
      highlightElevation: 0,
      borderSide: BorderSide(color: Colors.grey),
      child: Padding(
        padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Image(image: AssetImage("assets/google_logo.png"), height: 35.0),
            Padding(
              padding: const EdgeInsets.only(left: 10),
              child: Text(
                'Sign in with Google',
                style: TextStyle(
                  fontSize: 20,
                  color: Colors.grey,
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

这是所有Google和Firebase执行身份验证的页面。

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();

String name;
String email;
String imageUrl;

Future<String> signInWithGoogle() async {

  final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
  final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;

  final AuthCredential credential = GoogleAuthProvider.getCredential(
    accessToken: googleSignInAuthentication.accessToken,
    idToken: googleSignInAuthentication.idToken,
  );

  final AuthResult authResult = await _auth.signInWithCredential(credential);
  final FirebaseUser user = authResult.user;

  imageUrl = user.photoUrl;

  assert(!user.isAnonymous);
  assert(await user.getIdToken() != null);

  final FirebaseUser currentUser = await _auth.currentUser();
  assert(user.uid == currentUser.uid);

  //return 'signInWithGoogle succeeded: $user';
}

void signOutGoogle() async{
  await googleSignIn.signOut();
  theID = '';
  print("User Sign Out");
}

我听说默认情况下Firebase会持续用户身份验证,但我的程序中没有这种情况。有没有什么方法可以让用户身份验证持续到我按下注销按钮?如果你有什么想法,请告诉我。

bd1hkmkf

bd1hkmkf1#

Firebase存储持久授权,你只需要调用它!!
有两种方法可以解决这个问题:
1.Without Shared_pref-在这种方法中,您创建一个闪屏,它是应用的入口点(在此处添加应用徽标或其他内容),您可以在其中检查用户是否已登录,然后将其发送到主屏幕,否则将其发送到登录屏幕。

Future<void> _handleStartScreen() async {
    Auth _auth = Auth();

    if (await _auth.isLoggedIn()) {
      Navigator.popAndPushNamed(context, HomeScreen.id);
    } else {
      Navigator.popAndPushNamed(context, WelcomeScreen.id);
    }
  }

你可以从初始屏幕的initstate调用它。
2.使用Shared_pref:-这是更常用的方法。在这种情况下,你可以使用一个shared_preferences包(https://pub.dev/packages/shared_preferences#-readme-tab-,你可以从给定的链接中查看如何使用它)将auth状态存储在应用中。因此,每当用户登录时,使用logged_in = true在其中存储一个bool,每当应用启动时,你可以从启动画面中调用shared_preferences的示例。

ffvjumwh

ffvjumwh2#

截至2023年3月,Firebase Auth Flutter文档指出,默认情况下它是持久的,在iOS和Android上不可配置。

The Firebase SDKs for all platforms provide out of the box support for ensuring that your user's authentication state is persisted across app restarts or page reloads.

On native platforms such as Android & iOS, this behavior is not configurable and the user's authentication state will be persisted on-device between app restarts. The user can clear the apps cached data via the device settings which will wipe any existing state being stored.

Documentation
根据您接受的答案,我认为问题是您没有手动处理页面更改。
你可以在StreamBuilder中使用authStateChanges或者userChanges流,或者你甚至可以使用基于这个流的go_router重定向。我建议你使用流,这样应用程序可以更动态,你可以处理当前用户被删除(变成null,注销等)。

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: AuthenticationWrapper(),
      ),
    );
  }
}

class AuthenticationWrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final firebaseUserStream = FirebaseAuth.instance.userChanges();

    return StreamBuilder<User?>(
      stream: firebaseUserStream,
      builder: (BuildContext context, AsyncSnapshot<User?> snapshot) {
        if (snapshot.connectionState == ConnectionState.active) {
          if (snapshot.data == null) {
            // Show login page if the user is not logged in
            return LoginPage();
          } else {
            // Show home page if the user is logged in
            return HomePage();
          }
        } else {
          // Show a progress indicator while waiting for the stream
          return Center(child: CircularProgressIndicator());
        }
      },
    );
  }
}

GoRouter示例可能很长,但总结一下该方法:

  • 我使用的是单例AuthBloc,带有get_it和injectable
  • AuthBloc侦听userChanges流,并基于此发出状态,如已验证、未验证。
  • 因为块有流,所以我让GoRouter监听它。
final router = GoRouter(
   refreshListenable: GoRouterRefreshStream(getIt<AuthBloc>().stream),
   routes: [//some routes here]
   redirect: (context, state) async {
     final authState = getIt<AuthBloc>().state;
     final isUnauthenticated = authState is! Authenticated;
     final isAuthenticated = authState is Authenticated;
      // code where I return correct page based on Auth and other stuff.
    },

相关问题