简体   繁体   English

Firebase 身份验证未在 Flutter Web 上持续

[英]Firebase Authentication is not persisted on Flutter Web

I am using Firebase Authentication on my Flutter Web app, but the session is not persisted during refresh.我在我的 Flutter Web 应用程序上使用 Firebase 身份验证,但在刷新期间 Z21D6F40CFB515082E57ZE 没有持续存在。

This is the package I am using.这是我正在使用的 package。

https://pub.dev/packages/firebase https://pub.dev/packages/firebase

This is how I am authenticating with Firebase这就是我使用 Firebase 进行身份验证的方式

  static Future<User> handleSignInEmail(String email, String password) async {
    await init();

    final UserCredential userCredential =
        await auth().signInWithEmailAndPassword(email.trim(), password);

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

    final User currentUser = await userCredential.user;
    assert(userCredential.user.uid == currentUser.uid);

    print('signInEmail succeeded: $userCredential.user');

    return userCredential.user;
  }

If I refresh the page and call the following method, the user that is returned is null:如果我刷新页面并调用以下方法,返回的用户是null:

  static Future<User> getFirebaseUser() async {
    await init();
    return await auth().currentUser;
  }

A similar implementation using Flutter Mobile works as expected.使用 Flutter Mobile 的类似实现按预期工作。 What am I missing on the Flutter Web implementation?我在 Flutter Web 实现中缺少什么?

Login happens automatically and it is handled by Firebase, however in async way.登录会自动发生,并由 Firebase 处理,但以异步方式进行。 More details can be found in the official documentation:更多细节可以在官方文档中找到:

https://firebase.google.com/docs/auth/web/auth-state-persistence https://firebase.google.com/docs/auth/web/auth-state-persistence

The trick is very simple.诀窍很简单。 You need to wait for the first state change.您需要等待第一次状态更改。

  static Future<User> getFirebaseUser() async {
    await init();
    //return await auth().currentUser;
    return await auth().onAuthStateChanged.first;
  }

It returns null if there is no signed-in user: https://firebase.google.com/docs/reference/js/firebase.auth.Auth.html#onauthstatechanged如果没有登录用户,则返回nullhttps : //firebase.google.com/docs/reference/js/firebase.auth.Auth.html#onauthstatechanged

My firebase version:我的firebase版本:

firebase: 5.0.4 #https://pub.dartlang.org/packages/firebase

I wrote this implementation which works on both mobile and web:我写了这个适用于移动和网络的实现:

  static Future<FirebaseUser> getFirebaseUser() async {
    FirebaseUser firebaseUser = await FirebaseAuth.instance.currentUser();
    if (firebaseUser == null) {
      firebaseUser = await FirebaseAuth.instance.onAuthStateChanged.first;
    }
    return firebaseUser;
  }

Firebase Dart Package Firebase Dart 包

Import this pub and check the OS wherever auth is used导入此 pub 并在使用 auth 的任何地方检查操作系统

import 'package:firebase/firebase.dart' as firebase;
import 'package:firebase_auth/firebase_auth.dart';

if(Platform.isIOS || Platform.isAndroid) {
    FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password).then(() {
        //do something
    });
} else {
    firebase.auth().createUserWithEmailAndPassword(email, password).then(() {
        //do something
    });
}

Extension of https://stackoverflow.com/a/58158636 https://stackoverflow.com/a/58158636 的扩展

In the new library version, onAuthStateChanged getter is not available.在新的库版本中, onAuthStateChanged getter 不可用。 Instead of that use authStateChanges() .而不是使用authStateChanges()

User firebaseUser = await FirebaseAuth.instance.currentUser;
  if (firebaseUser == null) {
    firebaseUser = await FirebaseAuth.instance.authStateChanges().first;
  }

https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/authStateChanges.html https://pub.dev/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/authStateChanges.html

I'm using Flutter 3.0.5 and firebase_auth 3.6.4 and that's the only way I could make it work for web (Chrome):我正在使用 Flutter 3.0.5 和 firebase_auth 3.6.4,这是我可以使它适用于 web(Chrome)的唯一方法:

class HomePage extends StatefulWidget {
  const HomePage();

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  User? currentUser;
  late StreamSubscription<User?> userSubscription;

  @override
  void initState() {
    super.initState();
    userSubscription = FirebaseAuth.instance.authStateChanges().listen((user) {
      if (user != null) {
        setState(() {
          currentUser = user;
        });
      }
    });
  }

  @override
  void dispose() {
    userSubscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return currentUser != null
        ? Text('User is logged in')
        : Text('User is not logged in');
  }
}

As I understand, you need to wait until FirebaseAuth.instance.authStateChanges() returns non null value, but in the the beginning it returns null because there's something that still initializes in the background.据我了解,您需要等到FirebaseAuth.instance.authStateChanges()返回非 null 值,但一开始它返回 null 因为有些东西仍在后台初始化。 Same goes for FirebaseAuth.instance.currentUser , it will be null until some point, so if you check it immediately, you'll be stuck in unauthorized state unless you recheck it later somehow. FirebaseAuth.instance.currentUser也是如此,它将是 null 直到某个时候,所以如果你立即检查它,你将被困在未经授权的 state 除非你以后以某种方式重新检查它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM