You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web中google_sign_in的renderButton登录流程卡顿问题排查

Flutter Web Google Sign In卡在gsi/transform页面的解决方法

针对你遇到的选择谷歌账号后卡在https://accounts.google.com/gsi/transform页面,且控制台报Uncaught TypeError: Cannot read properties of null (reading "postMessage')的问题,结合你的代码和已做的配置,以下是可能的遗漏点及解决方法:

1. 未绑定renderButton的登录回调逻辑

renderButton仅负责渲染谷歌登录按钮,不会自动处理完整的登录流程。你需要手动绑定onPressed回调,触发GoogleSignIn的登录方法,并处理后续的凭证交换(尤其是结合Firebase Auth时)。

修正代码:

在renderButton中添加onPressed参数,绑定自定义登录方法:

renderButton(
  configuration: GSIButtonConfiguration(
    shape: GSIButtonShape.pill,
    size: GSIButtonSize.medium,
    logoAlignment: GSIButtonLogoAlignment.center,
  ),
  onPressed: _handleSignIn,
)

添加登录处理方法:

Future<void> _handleSignIn() async {
  setState(() {
    isLoading = true;
    _status = "正在登录...";
  });
  try {
    final account = await _gsi.signIn();
    if (account != null) {
      // 获取谷歌认证凭证并同步到Firebase Auth
      final authDetails = await account.authentication;
      final firebaseCredential = GoogleAuthProvider.credential(
        accessToken: authDetails.accessToken,
        idToken: authDetails.idToken,
      );
      await FirebaseAuth.instance.signInWithCredential(firebaseCredential);
      
      setState(() {
        _status = "登录成功: ${account.email}";
      });
    }
  } catch (e) {
    setState(() {
      _status = "登录失败: $e";
    });
  } finally {
    setState(() {
      isLoading = false;
    });
  }
}

2. 权限请求时机错误

你在onCurrentUserChanged回调中请求生日权限,此时用户可能尚未完成完整登录流程,容易导致权限请求失败并中断登录。建议将权限声明直接放在GoogleSignIn实例初始化时:

final GoogleSignIn _gsi = GoogleSignIn(
  clientId: '[MY_CLIENT_ID].apps.googleusercontent.com',
  scopes: ['https://www.googleapis.com/auth/user.birthday.read'], // 提前声明权限
);

3. Project IDX环境的特殊配置

Project IDX的预览URL为动态生成的域名(如https://xxxx-xxxx-xxxx-xxxx-xxxx.idx.googleusercontent.com),需确保:

  • 该完整URL(包含https://)已添加到谷歌云控制台的OAuth 2.0客户端ID的「已授权重定向URI」列表中
  • 在web/index.html的<head>中手动添加谷歌GSI脚本,确保加载顺序正确:
<script src="https://accounts.google.com/gsi/client" async defer></script>

4. 回调地址不匹配

谷歌OAuth要求重定向URI完全匹配,需检查:

  • 若使用Firebase Auth,需将https://<你的Firebase项目ID>.web.app/__/auth/handler添加到授权列表
  • 确保Project IDX的预览URL没有端口或路径错误(比如末尾是否带斜杠)

5. 版本兼容性问题

确保google_sign_in和firebase_auth依赖为最新版本,避免因版本不兼容导致的通信问题。在pubspec.yaml中更新依赖:

dependencies:
  google_sign_in: ^5.4.0
  firebase_auth: ^4.6.1

完整修正后的代码

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in_web/web_only.dart';
import 'package:google_sign_in/google_sign_in.dart';

class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final fireStoreInstance = FirebaseFirestore.instance;
  bool isLoading = false;
  String _status = "Checking login status...";
  UserCredential? tempCred;

  final GoogleSignIn _gsi = GoogleSignIn(
    clientId: '[MY_CLIENT_ID].apps.googleusercontent.com',
    scopes: ['https://www.googleapis.com/auth/user.birthday.read'],
  );
  GoogleSignInAccount? _currentUser;

  @override
  void initState() {
    super.initState();
    _gsi.onCurrentUserChanged.listen((GoogleSignInAccount? account) {
      setState(() {
        _currentUser = account;
        _status = account?.email ?? "未登录";
      });
    });
    // 尝试静默登录
    _gsi.signInSilently().catchError((e) {
      setState(() {
        _status = "静默登录失败: $e";
      });
    });
  }

  Future<void> _handleSignIn() async {
    setState(() {
      isLoading = true;
      _status = "正在登录...";
    });
    try {
      final account = await _gsi.signIn();
      if (account != null) {
        final authDetails = await account.authentication;
        final firebaseCredential = GoogleAuthProvider.credential(
          accessToken: authDetails.accessToken,
          idToken: authDetails.idToken,
        );
        await FirebaseAuth.instance.signInWithCredential(firebaseCredential);
        
        setState(() {
          _status = "登录成功: ${account.email}";
        });
      } else {
        setState(() {
          _status = "用户取消登录";
        });
      }
    } catch (e) {
      setState(() {
        _status = "登录失败: $e";
      });
    } finally {
      setState(() {
        isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).primaryColor,
        toolbarHeight: 50,
        actions: [
          IconButton(
            icon: const Icon(Icons.home_max_sharp),
            onPressed: () {
              Navigator.pop(context);
            },
          ),
        ],
      ),
      body: Center(
        child: isLoading
            ? Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const CircularProgressIndicator(),
                  const SizedBox(height: 20),
                  Text(_status),
                ],
              )
            : Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  const SizedBox(height: 20),
                  renderButton(
                    configuration: GSIButtonConfiguration(
                      shape: GSIButtonShape.pill,
                      size: GSIButtonSize.medium,
                      logoAlignment: GSIButtonLogoAlignment.center,
                    ),
                    onPressed: _handleSignIn,
                  ),
                  const SizedBox(height: 20),
                  Text(
                    _status,
                    style: const TextStyle(
                      fontSize: 16,
                      color: Colors.red,
                    ),
                  ),
                ],
              ),
      ),
    );
  }
}

最后检查

  • 清除浏览器缓存和Cookie,重新测试
  • 确认谷歌云控制台的OAuth同意屏幕已添加测试用户(若应用未发布)

内容的提问来源于stack exchange,提问作者Ari S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:27:01