Flutter - 如何使用 Firebase Auth 访问 StreamBuilder 中未来的价值

发布于 2025-01-20 07:06:54 字数 1711 浏览 0 评论 0 原文

我正在对我正在构建和使用云功能和自定义声明的基于订阅的应用程序使用 Firebase 身份验证,我确保用户只有在拥有有效订阅的情况下才能登录。

我的应用程序有一个登录页面,用于检查用户是否已登录,如果登录,则将他们带到应用程序主页。如果没有,则会显示登录屏幕。这是它的代码:

class LandingPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthBase>(context, listen: false);
    return StreamBuilder<User?>(
        stream: auth.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            User? user = snapshot.data;
            user?.reload();
            user = snapshot.data;

            if (user == null || user.emailVerified == false) {
              return SignInHomePage.create(context);
            }
            return Provider<User?>.value(
              value: user,
              child: DisclaimerAcceptanceHomeScreen(
                userName: user.displayName,
              ),
            );
          } else {
            return Scaffold(
              body: Center(
                child: PlatformCircularProgressIndicator(),
              ),
            );
          }
        });
  }
}

这非常适合获取用户数据并显示相关屏幕。唯一的问题是,我不知道如何将用户的订阅状态添加到此,以确保只有具有有效订阅的用户才会被定向到应用程序的主页。订阅状态自定义声明将作为未来返回。理论上,我想使用这样的东西:

  final idTokenResult =
      await FirebaseAuth.instance.currentUser?.getIdTokenResult(true);

然后:

idTokenResult?.claims!['status']

将用户返回到登录屏幕的理想条件是:

user == null || user.emailVerified == false || idTokenResult?.claims!['status'] != 'active'

这确实在异步/等待函数中工作,但您会看到我的登陆页面是无状态的小部件并且不是异步的。

如何修改着陆页代码,以允许我获取未来“状态”自定义声明值?我将不胜感激对此的任何建议。谢谢你!

I am using Firebase Authentication for a subscription-based app that I am building and using cloud functions and custom claims, I am ensuring that the user can only log in if they have an active subscription.

My app has a landing page, which checks to see if the user is logged in and if they are, they are taken to the app home page. If not, they are shown the login screen. This is the code for it:

class LandingPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthBase>(context, listen: false);
    return StreamBuilder<User?>(
        stream: auth.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            User? user = snapshot.data;
            user?.reload();
            user = snapshot.data;

            if (user == null || user.emailVerified == false) {
              return SignInHomePage.create(context);
            }
            return Provider<User?>.value(
              value: user,
              child: DisclaimerAcceptanceHomeScreen(
                userName: user.displayName,
              ),
            );
          } else {
            return Scaffold(
              body: Center(
                child: PlatformCircularProgressIndicator(),
              ),
            );
          }
        });
  }
}

This works perfectly to get the user data and show the relevant screen. The only problem is, I don't know how to add the user's subscription status to this, to ensure only a user with an active subscription will be directed to the app's home page. The subscription status custom claim is returned as a future. In theory I would want to use something like this:

  final idTokenResult =
      await FirebaseAuth.instance.currentUser?.getIdTokenResult(true);

and then:

idTokenResult?.claims!['status']

The ideal condition that would return a user to the login screen would be:

user == null || user.emailVerified == false || idTokenResult?.claims!['status'] != 'active'

This does work inside an async/await function but you'll see that my landing page is a stateless widget and is not asynchronous.

How can I modify the landing page code, to allow me to get the Future 'status' custom claim value? I would appreciate any suggestions on this. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼泪也成诗 2025-01-27 07:06:54

您是否考虑过在调用 getIdTokenResult 时使用 FutureBuilder

或者,您可以在 StreamBuilder >FirebaseAuth.instance.idTokenChanges() 以获取有关 ID 令牌的所有更新的通知。

Did you consider using a FutureBuilder around the call to getIdTokenResult?

Alternatively you can use a StreamBuilder on FirebaseAuth.instance.idTokenChanges() to get notified of all updates to the ID token.

つ低調成傷 2025-01-27 07:06:54

根据弗兰克(Frank)的评论,我修改了我的 streambuilder include futurebuilder ,其中未来是 getIdTokenResult(true)函数。这就是上述代码的样子,如所述进行了修改:

class LandingPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthBase>(context, listen: false);
    return StreamBuilder<User?>(
        stream: auth.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            User? user = snapshot.data;
            user?.reload();
            user = snapshot.data;

            return FutureBuilder<IdTokenResult>(
              future: user?.getIdTokenResult(true),
              builder: (
                BuildContext context,
                AsyncSnapshot<IdTokenResult> snapshotData,
              ) {
                if (user == null ||
                    user.emailVerified == false ||
                    snapshotData.data?.claims!['status'] != 'active') {
                  return SignInHomePage.create(context);
                } else {
                  return Provider<User?>.value(
                    value: user,
                    child: DisclaimerAcceptanceHomeScreen(
                      userName: user.displayName,
                    ),
                  );
                }
              },
            );
          } else {
            return Scaffold(
              body: Center(
                child: PlatformCircularProgressIndicator(),
              ),
            );
          }
        });
  }
}

现在允许我在让他们访问应用程序之前检查用户的订阅状态。

Based on Frank's comment, I modified my StreamBuilder to include FutureBuilder, where the future was the getIdTokenResult(true) function. This is what the above code looks like, modified as described:

class LandingPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthBase>(context, listen: false);
    return StreamBuilder<User?>(
        stream: auth.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            User? user = snapshot.data;
            user?.reload();
            user = snapshot.data;

            return FutureBuilder<IdTokenResult>(
              future: user?.getIdTokenResult(true),
              builder: (
                BuildContext context,
                AsyncSnapshot<IdTokenResult> snapshotData,
              ) {
                if (user == null ||
                    user.emailVerified == false ||
                    snapshotData.data?.claims!['status'] != 'active') {
                  return SignInHomePage.create(context);
                } else {
                  return Provider<User?>.value(
                    value: user,
                    child: DisclaimerAcceptanceHomeScreen(
                      userName: user.displayName,
                    ),
                  );
                }
              },
            );
          } else {
            return Scaffold(
              body: Center(
                child: PlatformCircularProgressIndicator(),
              ),
            );
          }
        });
  }
}

This now allows me to check the user's subscription status before letting them have access to the app.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文