使用Flutter web刷新后,如何维护Firebase身份验证



我正在使用来自带有flutter的Firebase的authStateChanges流。我有两个视图,一个用于移动,另一个用于web应用程序。如果用户没有连接、登录或身份验证,我想将其重定向到SignIn屏幕。起初它运行良好,但当我登录并刷新浏览器时,我加载了SignIn屏幕大约1秒,然后Web屏幕再次出现。我用print检查了正在发生的事情,从我看到的情况来看,authStateChanges Stream在1-2秒内为null(当SignIn屏幕出现时(,然后在流接收到连接的用户时有一个值。有没有一种方法可以检查,或者等到完成身份验证后再加载SignIn屏幕,而此时必须不加载它?

我的主要组件包含StreamBuilder,如下所示:

Widget build(BuildContext context) {
final firebaseAuthService = Provider.of<FirebaseAuthService>(context);
return StreamBuilder<User>(
stream: firebaseAuthService.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
User user = snapshot.data;
if (user == null) {
//first time no connection
return SignIn();
}
if (kIsWeb) {
return WebMain(user: user);
}
// load mobile version
return MobileMain();
}
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
});
}

在这里你可以找到我的FirebaseAuth包装类,它包含来自firebase:的方法

class FirebaseAuthService {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
User _user;
bool get isAuthenticated {
return _user == null ? false : true;
}
User get user {
return _user;
}
Future<User> signInWithEmailAndPassword(
String userEmail, String userPassword) async {
return _user = await _firebaseAuth
.signInWithEmailAndPassword(email: userEmail, password: userPassword)
.then((userCredential) => userCredential.user);
}
Stream<User> authStateChanges() {
_user = _firebaseAuth.currentUser;
return _firebaseAuth.authStateChanges();
}
Future<void> signOut() async {
return _firebaseAuth.signOut();
}
}

虽然我不知道为什么authStateChanges在用户登录状态更改时(通常在一秒钟后(不通知,但类似的函数似乎也适用于您的用例。

尝试idTokenChanges((

FirebaseAuth.instance.idTokenChanges().listen((event) {
print("On Data: ${event}");
});

此事件将返回您的Firebase User对象。刷新时,它最初可能会返回"null",但在一秒钟内会返回您的登录用户。您可能会让登录页等待几秒钟,以确保登录用户没有被初始化。

编辑:虽然可能有更好的解决方案,但这目前对我有效

final subscription = FirebaseAuth.instance.idTokenChanges().listen(null);
subscription.onData((event) async {
if(event != null) {
print("We have a user now");
isLoading = false;
print(FirebaseAuth.instance.currentUser);
subscription.cancel();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => OverviewController())
);
} else {
print("No user yet..");
await Future.delayed(Duration(seconds: 2));
if(isLoading) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LoginController())
);
isLoading = false;
subscription.cancel();
}
}
});

对我来说,下面的代码似乎工作得很好。尽管在文档中有一个警告说";您不应该使用此getter来确定用户的当前状态,而应该使用[authStateChanges]、[idTokenChanges]或[userChanges]来订阅更新">

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Diary Book',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
primarySwatch: Colors.green,
),
home: (FirebaseAuth.instance.currentUser == null)
? LoginPage()
: MainPage(),
);
}
}

我在使用上述代码时没有遇到任何问题。我会让你知道如果做。如果有人可以评论任何未来的错误,这将是伟大的

FirebaseAuth.instance.authStateChanges().listen(
(event) {
if (event == null) {
print('----user is currently signed out');
} else {
print('----user is signed in ');
}
runApp(
const MyApp()  
);
},
);

相关内容

  • 没有找到相关文章

最新更新