Google Drive授权后如何获取用户账户名?CredentialManager迁移遇阻
问题根源
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端点,获取用户的基本信息。
代码实现
- 先添加People API依赖到
build.gradle:
dependencies { implementation 'com.google.apis:google-api-services-people:v1-rev20240209-2.0.0' }
- 授权成功后调用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
相关产品推荐
相关产品推荐

