Android下用CredentialManager实现Google登录并授权Drive API遇问题求助
问题解决:Google登录认证与Drive API授权异常处理
一、GoogleIdTokenCredential的服务端验证处理
Google文档提到的服务端验证,核心是将拿到的ID Token发送至后端,通过Google官方接口校验合法性,具体操作如下:
- 从
googleIdTokenCredential中提取ID Token字符串:val idToken = googleIdTokenCredential.idToken - 后端接收该Token后,可通过两种方式验证:
- 直接调用Google验证端点:
https://oauth2.googleapis.com/tokeninfo?id_token=YOUR_ID_TOKEN,返回的响应包含用户邮箱、唯一ID等信息,可直接校验aud字段是否匹配你的客户端ID。 - 使用Google官方客户端库(以Java为例):
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) .setAudience(Collections.singletonList(你的客户端ID)) .build(); GoogleIdToken idToken = verifier.verify(tokenString); if (idToken != null) { Payload payload = idToken.getPayload(); String userId = payload.getSubject(); // 用户唯一标识 String email = payload.getEmail(); // 验证通过,处理后端登录逻辑 } else { // Token无效,拒绝登录请求 }
- 直接调用Google验证端点:
二、解决Drive API授权的空账户异常
当前授权流程未关联已登录账户,导致Identity服务无法确定授权主体,因此返回空GoogleSignInAccount,需从以下几点修改:
1. 保存已登录账户信息
在handleSignIn方法中,从googleIdTokenCredential提取账户信息并保存:
private var signedInAccount: GoogleSignInAccount? = null private fun handleSignIn(result: GetCredentialResponse) { when (val credential = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { result.credential } else { null }) { is CustomCredential -> { if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) { try { val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data) Log.d(TAG, "Google id token account name: ${googleIdTokenCredential.displayName}") // 从GoogleIdTokenCredential构建GoogleSignInAccount实例 signedInAccount = GoogleSignInAccount.Builder() .setEmail(googleIdTokenCredential.id) .setAccount(Account(googleIdTokenCredential.id, "com.google")) .build() requestGoogleDriveAuthorization() } catch (e: GoogleIdTokenParsingException) { Log.e(TAG, "Received an invalid google id token response", e) } } else { Log.e(TAG, "Unexpected type of credential") } } else -> Log.e(TAG, "Unexpected type of credential") } }
2. 授权时指定已登录账户
修改requestGoogleDriveAuthorization(),在AuthorizationRequest中关联已保存的账户:
private fun requestGoogleDriveAuthorization() { val requestedScopes = listOf(Scope(DriveScopes.DRIVE_READONLY)) val authorizationRequest = AuthorizationRequest.Builder() .setRequestedScopes(requestedScopes) .setAccount(signedInAccount?.account) // 绑定已登录账户 .build() Identity.getAuthorizationClient(requireContext()) .authorize(authorizationRequest) .addOnSuccessListener { authorizationResult -> // 原有逻辑保持不变 } .addOnFailureListener { e -> Log.e(TAG, "Failed to authorize", e) } }
3. 检查项目配置
- 确保Google Cloud Console中已启用Google Drive API;
- 在OAuth consent screen中,已添加
DriveScopes.DRIVE_READONLY至授权范围列表; - 验证客户端ID(Web端/Android端)配置正确,无拼写错误。
三、额外注意事项
- 若仅需客户端使用Drive API,可直接用
GoogleAccountCredential结合googleIdTokenCredential的账户信息构建凭证,但服务端验证是保障账号安全的必要步骤; - 在页面销毁时,需调用
cancellationSignal.cancel()终止未完成的CredentialManager请求,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Abdullah Al Nahian Kanon
相关产品推荐
相关产品推荐

