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

Google Drive授权后如何获取用户账户名?CredentialManager迁移遇阻

解决CredentialManager+Authorization API无法获取用户账户名的问题

问题根源

Authorization API的核心是获取访问令牌以调用Drive等服务,其返回的AuthorizationResult转换为GoogleSignInAccount后,默认不会包含用户的显示名称、邮箱等身份信息——即使你添加了PROFILE、EMAIL等Scope,因为这个流程的设计目标不是身份认证,而是权限授权。

可行解决方案

以下两种方式均无需弹出新窗口,可直接获取用户信息:

方案1:通过OpenID Connect获取ID Token并解析用户信息

在授权请求中显式请求ID Token,从ID Token中直接解析出用户的显示名称、邮箱等信息,无需额外API调用。

代码实现

确保你在Google Cloud Console中配置的OAuth客户端ID正确,然后修改授权请求:

// 替换为你的OAuth客户端ID
private static final String CLIENT_ID = "your-client-id.apps.googleusercontent.com";
private static final String TAG = "AuthDemo";

// 构建授权请求
List<Scope> requestedScopes = List.of(
        new Scope(DriveScopes.DRIVE_FILE),
        new Scope(Scopes.OPENID),
        new Scope(Scopes.PROFILE),
        new Scope(Scopes.EMAIL)
);

AuthorizationRequest authorizationRequest = AuthorizationRequest.builder()
        .setOptOutIncludingGrantedScopes(true)
        .setRequestedScopes(requestedScopes)
        // 关键:添加ID Token请求配置
        .setIdTokenRequestOptions(AuthorizationRequest.IdTokenRequestOptions.builder()
                .setClientId(CLIENT_ID)
                .setNonce(generateRandomNonce()) // 生成随机字符串防止重放攻击
                .build())
        .build();

// 发起授权请求
Identity.getAuthorizationClient(requireActivity())
        .authorize(authorizationRequest)
        .addOnSuccessListener(authorizationResult -> {
            if (authorizationResult.hasResolution()) {
                if (!check_only) {
                    try {
                        startIntentSenderForResult(
                                authorizationResult.getPendingIntent().getIntentSender(),
                                REQUEST_AUTHORIZE,
                                null, 0, 0, 0, null);
                    } catch (IntentSender.SendIntentException e) {
                        Log.e(TAG, "Authorization UI failed: " + e.getLocalizedMessage());
                    }
                } else {
                    mSavedAccount = null;
                }
            } else {
                mSavedAccount = authorizationResult;
                // 解析ID Token获取用户信息
                String idToken = authorizationResult.getIdToken();
                if (idToken != null) {
                    try {
                        GoogleIdToken googleIdToken = GoogleIdToken.parse(new JsonFactory(), idToken);
                        GoogleIdToken.Payload payload = googleIdToken.getPayload();
                        String displayName = payload.get("name").toString();
                        String email = payload.getEmail();
                        // 这里拿到的displayName可直接用于展示
                        Log.d(TAG, "用户昵称:" + displayName);
                    } catch (IOException e) {
                        Log.e(TAG, "解析ID Token失败", e);
                    }
                }
            }
        })
        .addOnFailureListener(e -> Log.e(TAG, "授权失败", e));

// 生成随机Nonce的工具方法
private String generateRandomNonce() {
    SecureRandom secureRandom = new SecureRandom();
    byte[] nonceBytes = new byte[16];
    secureRandom.nextBytes(nonceBytes);
    return Base64.encodeToString(nonceBytes, Base64.URL_SAFE | Base64.NO_WRAP);
}

方案2:调用Google People API获取用户资料

利用已获取的AccessToken调用People API的people/me端点,获取用户的基本信息。

代码实现

  1. 先添加People API依赖到build.gradle:
dependencies {
    implementation 'com.google.apis:google-api-services-people:v1-rev20240209-2.0.0'
}
  1. 授权成功后调用API:
// 授权成功后,从AuthorizationResult获取AccessToken
String accessToken = mSavedAccount.getAccessToken().getTokenValue();

// 构建People API客户端
People peopleService = new People.Builder(AndroidHttp.newCompatibleTransport(), new JsonFactory(), null)
        .setHttpRequestInitializer(request -> request.getHeaders().setAuthorization("Bearer " + accessToken))
        .build();

// 异步请求用户资料(避免主线程阻塞)
new AsyncTask<Void, Void, Person>() {
    @Override
    protected Person doInBackground(Void... voids) {
        try {
            return peopleService.people().get("people/me")
                    .setPersonFields("names,emailAddresses") // 指定需要获取的字段
                    .execute();
        } catch (IOException e) {
            Log.e(TAG, "获取用户信息失败", e);
            return null;
        }
    }

    @Override
    protected void onPostExecute(Person person) {
        if (person != null && !person.getNames().isEmpty()) {
            String displayName = person.getNames().get(0).getDisplayName();
            String email = person.getEmailAddresses().get(0).getValue();
            // 展示用户名
            Log.d(TAG, "用户昵称:" + displayName);
        }
    }
}.execute();

注意事项

  • 方案1无需额外API调用,效率更高,但需确保客户端ID配置正确,且Nonce生成符合安全规范。
  • 方案2需要添加People API的Scope(https://www.googleapis.com/auth/userinfo.profile或https://www.googleapis.com/auth/peopleapi.readonly),且必须处理异步网络请求逻辑。

内容的提问来源于stack exchange,提问作者Michael Kadykov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 02:42:45