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

Android下用CredentialManager实现Google登录并授权Drive API遇问题求助

问题解决:Google登录认证与Drive API授权异常处理

一、GoogleIdTokenCredential的服务端验证处理

Google文档提到的服务端验证,核心是将拿到的ID Token发送至后端,通过Google官方接口校验合法性,具体操作如下:

  1. 从googleIdTokenCredential中提取ID Token字符串:
    val idToken = googleIdTokenCredential.idToken
    
  2. 后端接收该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无效,拒绝登录请求
      }
      
    验证通过后,后端生成自有会话凭证返回给客户端,完成认证流程。

二、解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:44:53