本指南介绍了如何实现“使用 Google 账号登录”,并涵盖了以下步骤:
- 为应用添加依赖项。
- 实例化
CredentialManager。 - 创建底部动作条流程。
- 创建按钮流。
- 处理登录响应。
- 处理错误。
- 处理退出账号操作。
为应用添加依赖项
在模块的 build.gradle 文件中,使用最新版的 Credential Manager、Play 服务身份验证和 googleid 声明依赖项:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.6.0-rc02") implementation("androidx.credentials:credentials-play-services-auth:1.6.0-rc02") implementation("com.google.android.libraries.identity.googleid:googleid:<latest version>") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.6.0-rc02" implementation "androidx.credentials:credentials-play-services-auth:1.6.0-rc02" implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>" }
实例化 Credential Manager
使用应用或 activity 上下文创建 CredentialManager 对象。
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)
创建底部动作条流程
底部动作条是 Credential Manager 的内置界面。使用此界面可在所有身份验证方法(例如密码、通行密钥和“使用 Google 账号登录”)中提供一致的体验。
为之前已获授权的账号配置登录请求
尝试使用 GetGoogleIdOption 发出 Google 登录请求,以检索用户的 Google ID 令牌。
以下代码段用于检查账号是否为已获授权的账号。
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(true)
.setServerClientId(WEB_CLIENT_ID)
.setAutoSelectEnabled(true)
.setNonce(generateSecureRandomNonce())
.build()
请求 googleIdOption 对象的配置如下:
过滤之前已获授权的账号:如需检索之前曾用于登录您应用的已获授权的账号,请将
setFilterByAuthorizedAccounts设置为true。请注意,
setFilterByAuthorizedAccounts的默认值为true,这意味着底部动作条界面的默认行为是仅显示之前已获授权的账号。设置服务器客户端 ID:设置
setServerClientId参数。webClientId是您在完成前提条件时在 Google Cloud 项目中为 OAuth 设置的 Web 客户端 ID。启用自动登录功能(可选):如需为回访用户启用自动登录功能,请使用
setAutoSelectEnabled(true)和setFilterByAuthorizedAccounts(true)。对于应用用户,如果他们之前已登录,则可避免不必要的麻烦。只有在满足以下条件时,用户才能自动登录:
- 设备上只有一个已获授权的账号,并且该已获授权的账号之前曾用于登录设备上的应用。设备上的多个授权账号会停用自动登录功能。
- 用户在之前的会话期间未明确退出应用。
- 用户尚未在其 Google 账号设置中停用自动登录功能。
设置 Nonce(可选):如需增强安全性,请为服务器端验证设置 Nonce。为防止重放攻击,您可以添加一个随机数,以便使用
setNonce()进行服务器端验证。确保您的服务器端代码验证请求和响应 nonce 是否相同。如需生成 Nonce,请使用类似于以下 Functions 的函数,该函数会生成指定长度的加密型强随机 Nonce,并使用
Base64对其进行编码:
fun generateSecureRandomNonce(byteLength: Int = 32): String {
val randomBytes = ByteArray(byteLength)
SecureRandom().nextBytes(randomBytes)
return Base64.encodeToString(randomBytes, Base64.NO_WRAP or Base64.URL_SAFE or Base64.NO_PADDING)
}
请求登录
通过调用 getCredential 方法检查用户在设备上是否拥有已获授权的账号:
val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(googleIdOption)
.build()
coroutineScope {
try {
val result = credentialManager.getCredential(
request = request,
context = activityContext,
)
handleSignIn(result)
} catch (e: GetCredentialException) {
// Handle failures
}
}
配置在没有授权账号的情况下发出的登录请求
如果设备上没有应用的授权用户,则 CredentialManager 会返回 NoCredentialException。在这种情况下,请停用已获授权的账号过滤器,以便用户可以使用其他账号进行注册。
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false)
.setServerClientId(WEB_CLIENT_ID)
.setNonce(generateSecureRandomNonce())
.build()
接下来,请求登录,这与您为授权账号执行的操作类似。
创建按钮流程
如果您希望用户能够在以下情况下使用“使用 Google 账号登录”功能,请使用按钮:
- 用户关闭了 Credential Manager 底部动作条界面。
- 此设备上没有 Google 账号。
- 设备上的现有账号需要重新验证身份。
创建按钮界面
虽然可以使用 Jetpack Compose 按钮完成此操作,但您可以使用“使用 Google 账号登录”品牌推广指南页面中预先批准的品牌图标。
创建登录流程
使用 GetSignInWithGoogleOption 创建 Google 登录请求,以检索 Google ID 令牌。
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder(
serverClientId = WEB_CLIENT_ID
).setNonce(generateSecureRandomNonce())
.build()
接下来,请求登录,这与您对底部动作条界面执行的操作类似。
为底部动作条和按钮创建共享的登录功能
如需处理登录,请完成以下步骤:
- 使用 CredentialManager 的
getCredential()函数。如果响应成功,请提取CustomCredential,其类型应为GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL。 使用
GoogleIdTokenCredential.createFrom()方法将对象转换为GoogleIdTokenCredential。在信赖方服务器上验证凭据。
确保您已正确处理错误。
fun handleSign(result: GetCredentialResponse) {
// Handle the successfully returned credential.
val credential = result.credential
when (credential) {
is CustomCredential -> {
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
try {
// Use googleIdTokenCredential and extract the ID for server-side validation.
val googleIdTokenCredential = GoogleIdTokenCredential
.createFrom(credential.data)
} catch (e: GoogleIdTokenParsingException) {
Log.e(TAG, "Received an invalid google id token response", e)
}
} else {
// Catch any unrecognized 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 账号,并决定从其他账号登录。您可以在设置页面等位置提供此信息。
凭据提供程序可能会存储有效的凭据会话,并使用该会话来限制未来登录请求的登录选项。例如,它可以优先使用有效凭据,而不是任何其他可用凭据。
当用户从应用中退出账号时,请调用 API clearCredentialState() 方法以清除所有凭据提供程序的当前用户凭据状态。这会通知所有凭据提供方,应清除给定应用的所有已存储的凭据会话,以便在用户下次登录时提供完整的登录选项。