本文将介绍如何使用 Google ID 辅助库将“使用 Google 账号登录”底部动作条对话框从 Google Identity 服务 (GIS) 迁移到 Credentials Manager API。
使用 Credentials Manager API 的应用经过配置,可向最终用户提供一致的 Android 界面,会为用户保存不同的登录选项供其选择,包括启用了通行密钥的账号。建议使用该 Android API 来整合不同的凭据类型和提供方。从 Android 14 开始,用户还可以通过 Credential Manager API 使用第三方密码管理工具。
声明依赖项
在模块的 build.gradle
文件中,使用最新版本声明依赖项:
dependencies {
// ... other dependencies
implementation "androidx.credentials:credentials:<latest version>"
implementation "androidx.credentials:credentials-play-services-auth:<latest version>"
implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
}
按照相关说明设置您的 Google API 控制台项目。关于添加依赖项的指南,请遵循上述说明。
实例化 Google 登录请求
如需开始构建您的实现,请实例化 Google 登录请求。使用 GetGoogleIdOption
检索用户的 Google ID 令牌。
Kotlin
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(true)
.setServerClientId(SERVER_CLIENT_ID)
.build()
Java
GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(true)
.setServerClientId(SERVER_CLIENT_ID)
.build();
首先,您应调用该 API,并将 setFilterByAuthorizedAccounts
参数设置为 true
。如果没有可用的凭据,请再次调用该 API 并将 setFilterByAuthorizedAccounts
设置为 false
。
如果您希望尽可能让用户自动登录,请在 GetGoogleIdOption
请求中使用 setAutoSelectEnabled
启用该功能。当满足以下条件时,用户就能自动登录:
- 用户只有一个为您的应用保存的凭据。也就是说,一个已存的密码或一个已存的 Google 账号。
- 用户尚未在其 Google 账号设置中停用自动登录功能。
为了提高登录安全性并避免重放攻击,请使用 setNonce
在每个请求中添加 Nonce。详细了解如何生成 Nonce。
Kotlin
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(true)
.setServerClientId(SERVER_CLIENT_ID)
.setNonce(<nonce string to use when generating a Google ID token>)
.build()
Java
GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(true)
.setServerClientId(SERVER_CLIENT_ID)
.setNonce(<nonce string to use when generating a Google ID token>);
.build();
使用 Google 账号登录
设置“使用 Google 账号登录”流程的步骤如下:
- 实例化
GetCredentialRequest
,并添加在上文中创建的googleIdOption
以检索凭据。 - 将此请求传递给
getCredential()
(Kotlin) 或getCredentialAsync()
(Java) 调用以检索用户的可用凭据。 - API 成功运行后,提取存放
GoogleIdTokenCredential
数据结果的CustomCredential
。 CustomCredential
的类型应该等于GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL
的值。使用GoogleIdTokenCredential.createFrom
方法将该对象转换为GoogleIdTokenCredential
。- 如果转换成功,请提取
GoogleIdTokenCredential
的 ID,对其进行验证,并在服务器上对凭据进行身份验证。 - 如果转换失败并显示
GoogleIdTokenParsingException
,那么您可能需要更新“使用 Google 账号登录”库的版本。 - 捕获任何无法识别的自定义凭据类型。
Kotlin
val request: GetCredentialRequest = Builder()
.addGetCredentialOption(googleIdOption)
.build()
coroutineScope.launch {
try {
val result = credentialManager.getCredential(
request = request,
context = activityContext,
)
handleSignIn(result)
} catch (e: GetCredentialException) {
handleFailure(e)
}
}
fun handleSignIn(result: GetCredentialResponse) {
// Handle the successfully returned credential.
val credential = result.credential
when (credential) {
is PublicKeyCredential -> {
// Share responseJson such as a GetCredentialResponse on your server to
// validate and authenticate
responseJson = credential.authenticationResponseJson
}
is PasswordCredential -> {
// Send ID and password to your server to validate and authenticate.
val username = credential.id
val password = credential.password
}
is CustomCredential -> {
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
try {
// Use googleIdTokenCredential and extract id to validate and
// authenticate on your server.
val googleIdTokenCredential = GoogleIdTokenCredential
.createFrom(credential.data)
} catch (e: GoogleIdTokenParsingException) {
Log.e(TAG, "Received an invalid google id token response", e)
}
} else {
// Catch any unrecognized custom credential type here.
Log.e(TAG, "Unexpected type of credential")
}
}
else -> {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential")
}
}
}
Java
GetCredentialRequest request = new GetCredentialRequest.Builder()
.addGetCredentialOption(googleIdOption)
.build();
// Launch sign in flow and do getCredential Request to retrieve the credentials
credentialManager.getCredentialAsync(
requireActivity(),
request,
cancellationSignal,
<executor>,
new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() {
@Override
public void onResult(GetCredentialResponse result) {
handleSignIn(result);
}
@Override
public void onError(GetCredentialException e) {
handleFailure(e);
}
}
);
public void handleSignIn(GetCredentialResponse result) {
// Handle the successfully returned credential.
Credential credential = result.getCredential();
if (credential instanceof PublicKeyCredential) {
String responseJson = ((PublicKeyCredential) credential).getAuthenticationResponseJson();
// Share responseJson i.e. a GetCredentialResponse on your server to validate and authenticate
} else if (credential instanceof PasswordCredential) {
String username = ((PasswordCredential) credential).getId();
String password = ((PasswordCredential) credential).getPassword();
// Use id and password to send to your server to validate and authenticate
} else if (credential instanceof CustomCredential) {
if (GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.equals(credential.getType())) {
try {
// Use googleIdTokenCredential and extract id to validate and
// authenticate on your server
GoogleIdTokenCredential googleIdTokenCredential = GoogleIdTokenCredential.createFrom(((CustomCredential) credential).getData());
} catch (GoogleIdTokenParsingException e) {
Log.e(TAG, "Received an invalid Google ID token response", e);
}
} else {
// Catch any unrecognized custom credential type here.
Log.e(TAG, "Unexpected type of credential");
}
} else {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential");
}
}
“使用 Google 账号登录”按钮
Credential Manager 采用最新的 Google ID 辅助库,支持“使用 Google 账号登录”按钮。如需触发“使用 Google 账号登录”按钮流程,请使用 GetSignInWithGoogleOption
而非 GetGoogleIdOption
,并按照与之前相同的方式处理返回的 GoogleIdTokenCredential
。
注册 Google 账号
如果在将 setFilterByAuthorizedAccounts
设置为 true
后同时实例化 GetGoogleIdOption
请求并传递到 GetCredentialsRequest
时未返回任何结果,则表示没有用于登录的已获授权的账号。此时,您应该设置 setFilterByAuthorizedAccounts(false)
并调用注册 Google 账号。
Kotlin
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false)
.setServerClientId(SERVER_CLIENT_ID)
.build()
Java
GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false)
.setServerClientId(SERVER_CLIENT_ID)
.build();
实例化 Google 账号注册请求后,按照使用 Google 账号登录部分中所述的相似方式启动身份验证流程。
处理退出账号操作
当用户从应用中退出账号时,请调用 API clearCredentialState()
方法以清除当前用户凭据状态并重置内部登录状态。