Flutter 基于google验证登录实现
注: 已实现登录Flutter端全部功能 基于
google_sign_in: ^7.1.1
#可选【如果找不到包的话 可以导入】
# google_sign_in_web: ^1.0.0
# google_sign_in_platform_interface: ^3.0.0
代码实现为
class AuthService extends GetxService{//从 Google Cloud Console 获取的后端 Web Client IDfinal String? _serverClientId = kIsWeb? null:'******.apps.googleusercontent.com';//Flutter Web Client ID,用于 Web 端的初始化final String? _webClientId = '******.apps.googleusercontent.com';String _errorMessage = '';// 根据平台选择不同的后端 URLfinal String AuthUrl = kIsWeb? "https://localhost/api/auth/google/": "https://localhost/api/auth/google/";final _storage = GsUtil.to;final GoogleSignIn _googleSignIn = GoogleSignIn.instance;GoogleSignIn get googleSignIn => _googleSignIn;@overridevoid onInit() async{await initialize();super.onInit();unawaited(_googleSignIn.initialize(clientId: _webClientId, serverClientId: _serverClientId).then((_) {_googleSignIn.authenticationEvents.listen(_handleAuthenticationEvent).onError(_handleAuthenticationEvent);/// This example always uses the stream-based approach to determining/// which UI state to show, rather than using the future returned here,/// if any, to conditionally skip directly to the signed-in state._googleSignIn.attemptLightweightAuthentication();}));}@overridevoid onClose(){super.onClose();}var isLoading = true.obs;// 初始化 GoogleSignIn 实例Future<void> initialize() async {try {await _googleSignIn.initialize(clientId: kIsWeb ? _webClientId : null,serverClientId: _serverClientId,);if(kIsWeb){final web.GoogleSignInPlugin _webPlugin = web.GoogleSignInPlugin();await _webPlugin.init(InitParameters(clientId: _webClientId,serverClientId: _serverClientId,),);}} catch (error) {debugPrint("Google Sign-In 初始化失败: $error");} finally {//无论成功或失败,最后都必须将 loading 状态设为 false**isLoading.value = false;}}// 触发登录流程Future<void> signIn() async {try {await _googleSignIn.authenticate();} catch (e) {debugPrint("authenticate error: $e");}}final List<String> scopes = <String>['email','profile', //可选 获取基础信息 头像 名称 等'https://www.googleapis.com/auth/user.phonenumbers.read', //可选 获取绑定手机号// 'https://www.googleapis.com/auth/contacts.readonly',];// 在获取到 user 对象后,调用此方法与后端通信/*** nickName 用户昵称* areaCode 电话区号* phone 手机号* vCode 邀请码*/String nickName="";String areaCode = "91";String phone = "";String vCode = "";Future<String?> exchangeCodeForToken(GoogleSignInAccount user) async {final LoadingController _loadingController = Get.find<LoadingController>();try {String serverAuthCode = "";_loadingController.show();// if(context.mounted) {// DialogUtil.showLoadingDialog(context);// }// 关键步骤:请求服务器授权码try {final GoogleSignInServerAuthorization? serverAuth = await user.authorizationClient.authorizeServer(scopes);serverAuthCode = serverAuth == null ? '' : serverAuth.serverAuthCode;if (TextUtil.isEmpty(serverAuthCode)) {throw Exception("Failed to obtain Server Auth Code!");}} on GoogleSignInException catch (e) {_errorMessage = _errorMessageFromSignInException(e);}debugPrint("获取到 Server Auth Code,正在发送到后端...");final di = SpUtil.to?.readString(Config.deviceID);// 将 code 发送到 后端final response = await http.post(Uri.parse(AuthUrl),headers: {'Content-Type': 'application/json'},// Body 的 key 必须是 "code"body: jsonEncode({'code': serverAuthCode)}),);if (response.statusCode == 200) {final data = jsonDecode(response.body);final String jwtToken = data['access_token']; // 后端 返回的 keyawait _storage?.writeString("jwtToken", jwtToken);debugPrint("后端验证成功,已登录!");return jwtToken;} else {throw Exception("后端处理 code 失败: ${response.body}");}} catch (e) {debugPrint("exchangeCodeForToken error: $e");return null;}finally{_loadingController.hide();}}// 登出Future<void> signOut() async {await googleSignIn.disconnect();}//回调Future<void> _handleAuthenticationEvent(GoogleSignInAuthenticationEvent event) async {final GoogleSignInAccount? user = switch (event) {GoogleSignInAuthenticationEventSignIn() => event.user,GoogleSignInAuthenticationEventSignOut() => null,};final GoogleSignInClientAuthorization? authorization = await user?.authorizationClient.authorizationForScopes(scopes);if (user != null && authorization != null) {unawaited(exchangeCodeForToken(user));}}String _errorMessageFromSignInException(GoogleSignInException e) {return switch (e.code) {GoogleSignInExceptionCode.canceled => 'Sign in canceled',_ => 'GoogleSignInException ${e.code}: ${e.description}',};}//按钮逻辑Widget buildGoogleSignInButton() {if (kIsWeb) {return web_only.renderButton(configuration: web.GSIButtonConfiguration(type: web.GSIButtonType.icon,theme: web.GSIButtonTheme.outline,size: web.GSIButtonSize.large,text: web.GSIButtonText.continueWith,shape: web.GSIButtonShape.pill,// locale: ,minimumWidth: 45.0,// logoAlignment: web.GSIButtonLogoAlignment.left),);} else {// 移动端就用普通按钮if (GoogleSignIn.instance.supportsAuthenticate()){return GoogleSignInButton(onPressed: () async {if (Click.intervalClick(needTime: 2)) {await signIn();}},);}}return SizedBox(); // const Text('This platform does not have a known authentication method')}
}
以上就是核心工具类 踩了不少坑 自 github-google_sign 中抽取而出,都是精华
列位共勉