1、Flutter Google登录插件
2、实现使用“使用 Google 账号登录”的身份验证
3、使用后端服务器进行身份验证
第一步、设置 Google Cloud Console 项目,创建两个客户端:Android端、Web端(服务器端验证idToken时,需要用到)
第二步,flutter项目里集成Flutter Google登录插件
点击插件的Readme里Github Example
创建界面文件以及更改图中的Android ClientId和Web ClientID
运行起来,可以授权返回数据,这时如果你使用
print(user?.authentication.idToken);语句,然后在Flutte控制台拿到idToken,那恭喜你,你拿着这串字符串,在下面的Python程序中,将会得到:
ID Token verification failed: Could not verify token signature.
这里我被硬控了2个小时,哈哈哈哈哈哈!!!!!!!!!!!!!!!
啥原因呢?后面会给出答案。
第三步:Python端代码验证idToken的完整性,以及取出idToken的携带用户信息
(1)按照必备的依赖包:
pip install google-auth requests
(2)使用后端服务器进行身份验证
【Python版本】
from google.oauth2 import id_token
from google.auth.transport import requests
# (Receive token by HTTPS POST)
# ...
try:
id_token_str = "Android端拿到的idToken字符串"
WEB_CLIENT_ID = "Web端的ClientID,即Flutter配置的serverClientId"
# Specify the WEB_CLIENT_ID of the app that a***esses the backend:
idinfo = id_token.verify_oauth2_token(id_token_str, requests.Request(), WEB_CLIENT_ID)
# Or, if multiple clients a***ess the backend server:
# idinfo = id_token.verify_oauth2_token(token, requests.Request())
# if idinfo['aud'] not in [WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_CLIENT_ID_3]:
# raise ValueError('Could not verify audience.')
# If the request specified a Google Workspace domain
# if idinfo['hd'] != DOMAIN_NAME:
# raise ValueError('Wrong domain name.')
# ID token is valid. Get the user's Google A***ount ID from the decoded token.
# This ID is unique to each Google A***ount, making it suitable for use as a primary key
# during a***ount lookup. Email is not a good choice because it can be changed by the user.
userid = idinfo['sub']
#根据google user id或者email去自己的数据库查找是否已注册用户,注册的话,就是登录,返回自己的Token;
#没注册的话,程序新增一条用户记录,返回自己的Token即可。
print(idinfo)
except ValueError as e:
# Token 无效、过期、签名错误、受众不匹配等任何验证失败都会抛出 ValueError
print(f"ID Token verification failed: {e}")
except Exception as e:
# 处理网络错误或其他未知错误
print(f"An unexpected error o***urred during verification: {e}")
至此,集成完成。
思考:
1、为何Google第三方登录和国内平台的第三方登录返回的方式不同,哪种较好呢?
(1)Google返回的是Google私钥签名后的JWT 字符串,按点号分开的第二段Base 64解密后即是用户的一些信息:邮箱、google_user_id、昵称。后端需要使用Google提供的auth库(使用 Google 的公钥(以 JWK 或 PEM 格式提供)验证令牌的签名)进行校验完整性,才信任第二段的用户信息。即使第二段被修改校验是不会通过的。
(2)国内平台都是返回一个临时的用户凭证,然后服务端再拿这个凭证去获取用户的具体信息。
解答:
上面使用print(user?.authentication.idToken);语句从Flutter控制台打印出来字符串,会永远报错:
ID Token verification failed: Could not verify token signature.
是因为该idToken字符串不全,因为idToken字符串 被 Flutter 控制台截断了。
Flutter 的 print() 函数在 Android/iOS 上通常只会打印前 1000 个字符,剩下的会被截断丢弃。
可以使用下面方法打印出全部,或者Debug拿到。
void printFullToken(String? text) {
if (text == null) {
print("Token is null");
return;
}
final pattern = RegExp('.{1,800}'); // 每800个字符切一段
pattern.allMatches(text).forEach((match) => print(match.group(0)));
}