使用电话号码进行 Firebase 身份验证 (Android)

使用 Firebase 身份验证,您可以向用户的电话发送短信协助其登录,用户使用短信中包含的一次性验证码即可登录。

如需向应用中添加电话号码登录方式,最简单的方法就是使用 FirebaseUI。该库中包含一个普适性登录 widget,可为电话号码登录、基于密码登录和联合登录实现登录流程。本文档介绍了如何使用 Firebase SDK 实现电话号码登录流程。

准备工作

  1. 将 Firebase 添加到您的 Android 项目(如果尚未添加)。
  2. 在您的模块(应用级)Gradle 文件(通常是 <project>/<app-module>/build.gradle.kts<project>/<app-module>/build.gradle)中,添加 Firebase Authentication Android 库的依赖项。我们建议使用 Firebase Android BoM 来实现库版本控制。

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth-ktx")
    }
    

    借助 Firebase Android BoM,可确保您的应用使用的始终是 Firebase Android 库的兼容版本。

    (替代方法) 在不使用 BoM 的情况下添加 Firebase 库依赖项

    如果您选择不使用 Firebase BoM,则必须在每个 Firebase 库的依赖项行中指定相应的库版本。

    请注意,如果您在应用中使用多个 Firebase 库,我们强烈建议您使用 BoM 来管理库版本,从而确保所有版本都兼容。

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth-ktx:22.1.2")
    }
    

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth")
    }
    

    借助 Firebase Android BoM,可确保您的应用使用的始终是 Firebase Android 库的兼容版本。

    (替代方法) 在不使用 BoM 的情况下添加 Firebase 库依赖项

    如果您选择不使用 Firebase BoM,则必须在每个 Firebase 库的依赖项行中指定相应的库版本。

    请注意,如果您在应用中使用多个 Firebase 库,我们强烈建议您使用 BoM 来管理库版本,从而确保所有版本都兼容。

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth:22.1.2")
    }
    
  3. 如果您尚未将自己的应用与 Firebase 项目关联,请在 Firebase 控制台中进行关联。
  4. 如果您尚未在 Firebase 控制台中设置该应用的 SHA-1 哈希,请执行此操作。如需了解如何查找应用的 SHA-1 哈希,请参阅对客户端进行身份验证

安全考量

与其他可用的方法相比,仅使用电话号码进行身份验证的方法虽然便捷,但安全性较低,因为电话号码的所有权可以很容易地在用户之间转移。此外,在具有多份用户个人资料的设备上,任何一位可以接收短信的用户都能使用该设备的电话号码登录帐号。

如果您选择在应用中使用电话号码登录方法,应同时提供更安全的登录方法,并将使用电话号码登录的安全隐患告知用户。

为 Firebase 项目启用电话号码登录方法

如需让用户能够通过短信登录,您必须先为 Firebase 项目启用电话号码登录方法,步骤如下:

  1. Firebase 控制台中,打开 Authentication 部分。
  2. Sign-in Method(登录方法)页面上,启用电话号码登录方法。

Firebase 的电话号码登录请求的配额非常充足,大多数应用都不会遇到配额问题。但是,如果有大量用户需要通过电话号码身份验证方法进行登录,您可能需要升级定价方案。请参阅价格页面。

启用应用验证

如需使用电话号码身份验证,Firebase 必须要能验证电话号码登录请求是否来自您的应用。Firebase Authentication 可通过以下三种方法完成此操作:

  • Play Integrity API:如果用户的设备安装了 Google Play 服务,并且 Firebase Authentication 可以使用 Play Integrity API 验证设备的合法性,就可以继续使用电话号码登录方法。Firebase Authentication 会在 Google 拥有的项目(而不是您自己的项目)上启用 Play Integrity API;因此不会计入您项目的 Play Integrity API 配额。Play Integrity 支持 Authentication SDK v21.2.0+ (Firebase BoM v31.4.0+)。

    如需使用 Play Integrity,请在 Firebase 控制台的项目设置中指定应用的 SHA-256 指纹(如果您尚未执行此操作)。如需详细了解如何获取您的应用的 SHA-256 指纹,请参阅对客户端进行身份验证

  • reCAPTCHA 验证:如果用户设备上未安装 Google Play 服务,或者其他原因导致无法使用 Play Integrity,Firebase Authentication 会使用 reCAPTCHA 验证来完成电话号码登录流程。reCAPTCHA 验证通常可以在不需要用户回答任何问题的情况下完成。请注意,此流程要求您的应用关联 SHA-1。此外,此流程还要求确保您的 API 密钥在 PROJECT_ID.firebaseapp.com 上不受限制或已列入许可名单。

    在以下情形中,系统会触发 reCAPTCHA:

    • 如果最终用户的设备未安装 Google Play 服务。
    • 如果相关应用未通过 Google Play 商店分发(针对 Authentication SDK 21.2.0 及以上版本)。
    • 如果获得的 SafetyNet 令牌无效(针对 21.2.0 以下的 Authentication SDK 版本)。

    将 SafetyNet 或 Play Integrity 用于应用验证时,系统会用 Google Play 商店中所确定的应用名称来填充短信模板中的 %APP_NAME% 字段。 在触发 reCAPTCHA 的情形下,%APP_NAME% 会填充为 PROJECT_ID.firebaseapp.com

您可以通过 forceRecaptchaFlowForTesting 强制执行 reCAPTCHA 验证流程;也可以使用 setAppVerificationDisabledForTesting 停用应用验证(使用虚构电话号码时)。

问题排查

  • 使用 reCAPTCHA 进行应用验证时发生“缺少初始状态”错误

    如果 reCAPTCHA 流程成功完成,但未将用户重定向回原生应用,就可能会发生这种情况。如果发生这种情况,系统会将用户重定向到后备网址 PROJECT_ID.firebaseapp.com/__/auth/handler。在 Firefox 浏览器中,系统默认禁止打开原生应用链接。如果您在 Firefox 上看到上述错误,请按照设置 Firefox(Android 版)打开原生应用中的链接中的步骤操作,以允许打开应用链接。

向用户的电话发送验证码

如需启动电话号码登录流程,请向用户显示一个提示其输入电话号码的界面。虽然相关的法律要求可能不尽相同,但为了避免用户不满,最佳做法是告知用户,如果他们选择使用电话号码登录方式,则可能会收到一条验证短信,并需按标准费率支付短信费用。

然后,将用户的电话号码传递给 PhoneAuthProvider.verifyPhoneNumber 方法,请求 Firebase 验证该电话号码。例如:

Kotlin+KTX

val options = PhoneAuthOptions.newBuilder(auth)
    .setPhoneNumber(phoneNumber) // Phone number to verify
    .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
    .setActivity(this) // Activity (for callback binding)
    .setCallbacks(callbacks) // OnVerificationStateChangedCallbacks
    .build()
PhoneAuthProvider.verifyPhoneNumber(options)

Java

PhoneAuthOptions options = 
  PhoneAuthOptions.newBuilder(mAuth) 
      .setPhoneNumber(phoneNumber)       // Phone number to verify
      .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
      .setActivity(this)                 // (optional) Activity for callback binding
      // If no activity is passed, reCAPTCHA verification can not be used.
      .setCallbacks(mCallbacks)          // OnVerificationStateChangedCallbacks
      .build();
  PhoneAuthProvider.verifyPhoneNumber(options);     

verifyPhoneNumber 方法是可重入的:如果您对其进行多次调用(例如在某个 activity 的 onStart 方法中调用),除非原始请求已超时,否则 verifyPhoneNumber 方法将不会发送第二条短信。

如果您的应用在用户成功登录前关闭(例如,当用户正在使用其短信应用时),则可以利用此行为继续完成电话号码登录流程。在您调用 verifyPhoneNumber 方法后,设置一个表示正在进行验证的标志。然后,在您的 Activity 的 onSaveInstanceState 方法中保存该标志,并在 onRestoreInstanceState 方法中恢复该标志。最后,在该 Activity 的 onStart 方法中检查是否已在进行验证,如果是,则再次调用 verifyPhoneNumber 方法。务必在验证完成或失败时清除该标志(请参阅验证回调函数)。

为了轻松处理屏幕旋转以及涉及 Activity 重启的其他情况,请将您的 Activity 传递给 verifyPhoneNumber 方法。当 Activity 停止时,系统将自动取消与回调函数的关联,因此您可以在回调方法中自由编写界面转换代码。

您还可以在 Auth 实例的 setLanguageCode 方法中指定身份验证语言,对 Firebase 发送的短信进行本地化。

Kotlin+KTX

auth.setLanguageCode("fr")
// To apply the default app language instead of explicitly setting it.
// auth.useAppLanguage()

Java

auth.setLanguageCode("fr");
// To apply the default app language instead of explicitly setting it.
// auth.useAppLanguage();

在调用 PhoneAuthProvider.verifyPhoneNumber 方法时,您还必须提供一个 OnVerificationStateChangedCallbacks 的实例,该实例包含了负责处理请求结果的回调函数的实现代码。例如:

Kotlin+KTX

callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

    override fun onVerificationCompleted(credential: PhoneAuthCredential) {
        // This callback will be invoked in two situations:
        // 1 - Instant verification. In some cases the phone number can be instantly
        //     verified without needing to send or enter a verification code.
        // 2 - Auto-retrieval. On some devices Google Play services can automatically
        //     detect the incoming verification SMS and perform verification without
        //     user action.
        Log.d(TAG, "onVerificationCompleted:$credential")
        signInWithPhoneAuthCredential(credential)
    }

    override fun onVerificationFailed(e: FirebaseException) {
        // This callback is invoked in an invalid request for verification is made,
        // for instance if the the phone number format is not valid.
        Log.w(TAG, "onVerificationFailed", e)

        if (e is FirebaseAuthInvalidCredentialsException) {
            // Invalid request
        } else if (e is FirebaseTooManyRequestsException) {
            // The SMS quota for the project has been exceeded
        } else if (e is FirebaseAuthMissingActivityForRecaptchaException) {
            // reCAPTCHA verification attempted with null Activity
        }

        // Show a message and update the UI
    }

    override fun onCodeSent(
        verificationId: String,
        token: PhoneAuthProvider.ForceResendingToken,
    ) {
        // The SMS verification code has been sent to the provided phone number, we
        // now need to ask the user to enter the code and then construct a credential
        // by combining the code with a verification ID.
        Log.d(TAG, "onCodeSent:$verificationId")

        // Save verification ID and resending token so we can use them later
        storedVerificationId = verificationId
        resendToken = token
    }
}

Java

mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

    @Override
    public void onVerificationCompleted(@NonNull PhoneAuthCredential credential) {
        // This callback will be invoked in two situations:
        // 1 - Instant verification. In some cases the phone number can be instantly
        //     verified without needing to send or enter a verification code.
        // 2 - Auto-retrieval. On some devices Google Play services can automatically
        //     detect the incoming verification SMS and perform verification without
        //     user action.
        Log.d(TAG, "onVerificationCompleted:" + credential);

        signInWithPhoneAuthCredential(credential);
    }

    @Override
    public void onVerificationFailed(@NonNull FirebaseException e) {
        // This callback is invoked in an invalid request for verification is made,
        // for instance if the the phone number format is not valid.
        Log.w(TAG, "onVerificationFailed", e);

        if (e instanceof FirebaseAuthInvalidCredentialsException) {
            // Invalid request
        } else if (e instanceof FirebaseTooManyRequestsException) {
            // The SMS quota for the project has been exceeded
        } else if (e instanceof FirebaseAuthMissingActivityForRecaptchaException) {
            // reCAPTCHA verification attempted with null Activity
        }

        // Show a message and update the UI
    }

    @Override
    public void onCodeSent(@NonNull String verificationId,
                           @NonNull PhoneAuthProvider.ForceResendingToken token) {
        // The SMS verification code has been sent to the provided phone number, we
        // now need to ask the user to enter the code and then construct a credential
        // by combining the code with a verification ID.
        Log.d(TAG, "onCodeSent:" + verificationId);

        // Save verification ID and resending token so we can use them later
        mVerificationId = verificationId;
        mResendToken = token;
    }
};

验证回调函数

在大多数应用中,您需要实现 onVerificationCompletedonVerificationFailedonCodeSent 回调函数。此外可能还需要实现 onCodeAutoRetrievalTimeOut 方法,具体取决于应用的要求。

onVerificationCompleted(PhoneAuthCredential)

在下列两种情况下会调用此方法:

  • 即时验证:在某些情况下可以即时验证电话号码,而无需发送或输入验证码。
  • 自动检索:在某些设备上,Google Play 服务可以自动检测收到的验证短信并进行验证,而无需用户执行任何操作。(某些运营商可能不支持这项功能。)此情况下会使用 SMS Retriever API,该 API 会在短信末尾添加 11 个字符的哈希。
在上述任何一种情况下,系统都会成功验证用户的电话号码,并且您可以使用传递给该回调函数的 PhoneAuthCredential 对象来让该用户登录

onVerificationFailed(FirebaseException)

调用此方法的目的是响应无效的验证请求(例如所指定的电话号码或验证码无效的请求)。

onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken)

可选。通过短信将验证码发送到所提供的电话号码后,可调用此方法。

当调用此方法时,大多数应用会显示一个界面,提示用户输入短信中的验证码。(同时,系统可能正在后台进行自动验证。)当用户输入验证码后,您便可使用该验证码和之前传递给该方法的验证 ID 来创建 PhoneAuthCredential 对象,然后使用该对象让用户登录。但是,有些应用可能会等到 onCodeAutoRetrievalTimeOut 被调用之后才会显示验证码界面(不推荐此做法)。

onCodeAutoRetrievalTimeOut(String verificationId)

可选。如果没有先触发 onVerificationCompleted 方法,在指定给 verifyPhoneNumber 的超时时长过去后,可调用此方法。在没有 SIM 卡的设备上,由于不能进行短信自动检索,因此系统会立即调用此方法。

有些应用在自动验证期会阻止用户输入,直到自动验证期超时后,才会显示一个界面提示用户输入短信中的验证码(不推荐此做法)。

创建 PhoneAuthCredential 对象

在用户输入 Firebase 发送至用户手机的验证码后,使用该验证码和之前传递给 onCodeSentonCodeAutoRetrievalTimeOut 回调函数的验证 ID 创建一个 PhoneAuthCredential 对象。(调用 onVerificationCompleted 方法时,您将直接获得一个 PhoneAuthCredential 对象,因此可以跳过这一步骤。)

如需创建 PhoneAuthCredential 对象,请调用 PhoneAuthProvider.getCredential

Kotlin+KTX

val credential = PhoneAuthProvider.getCredential(verificationId!!, code)

Java

PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);

登录用户

在您获取了 PhoneAuthCredential 对象(无论是在 onVerificationCompleted 回调函数中还是通过调用 PhoneAuthProvider.getCredential 方法获取)后,将 PhoneAuthCredential 对象传递给 FirebaseAuth.signInWithCredential 方法以完成登录流程:

Kotlin+KTX

private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
    auth.signInWithCredential(credential)
        .addOnCompleteListener(this) { task ->
            if (task.isSuccessful) {
                // Sign in success, update UI with the signed-in user's information
                Log.d(TAG, "signInWithCredential:success")

                val user = task.result?.user
            } else {
                // Sign in failed, display a message and update the UI
                Log.w(TAG, "signInWithCredential:failure", task.exception)
                if (task.exception is FirebaseAuthInvalidCredentialsException) {
                    // The verification code entered was invalid
                }
                // Update UI
            }
        }
}

Java

private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithCredential:success");

                        FirebaseUser user = task.getResult().getUser();
                        // Update UI
                    } else {
                        // Sign in failed, display a message and update the UI
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            // The verification code entered was invalid
                        }
                    }
                }
            });
}

使用虚构的电话号码进行测试

您可以通过 Firebase 控制台设置虚构电话号码以用于开发。使用虚构的电话号码进行测试具有以下优势:

  • 测试电话号码身份验证时不会占用使用量配额。
  • 测试电话号码身份验证时无需发送实际的短信。
  • 可使用同一电话号码运行连续测试,而不会受到短信发送数量的限制。如果审核人员恰好使用相同的电话号码进行测试,这项优势会使在 App Store 审核过程中遭拒的风险降至最低。
  • 无需其他操作即可在开发环境中轻松进行测试,例如可以在 iOS 模拟器或没有 Google Play 服务的 Android 模拟器中进行开发。
  • 可编写集成测试,而不会被通常在生产环境中应用于真实电话号码的安全检查所屏蔽。

虚构的电话号码必须满足以下要求:

  1. 请确保使用确属虚构且不存在的电话号码。Firebase Authentication 不允许您将真实用户使用的现有电话号码设为测试号码。您可以使用以 555 为前缀的数字作为美国测试电话号码,例如:+1 650-555-3434
  2. 电话号码必须采用正确的格式,以符合长度要求和其他限制。这些电话号码仍将与真实用户的电话号码一样经过相同的验证。
  3. 您最多可以添加 10 个电话号码用于开发。
  4. 使用难以猜到的测试电话号码/验证码,并经常更换。

创建虚构的电话号码和验证码

  1. Firebase 控制台中,打开 Authentication 部分。
  2. Sign in method(登录方法)标签页中,启用电话号码提供方(如果您尚未启用)。
  3. 打开用于测试的电话号码折叠菜单。
  4. 提供您想要用于测试的电话号码,例如 +1 650-555-3434
  5. 为该特定号码提供 6 位验证码,例如 654321
  6. 添加该号码。如有需要,您可以删除电话号码及其验证码,只需将鼠标悬停在相应的行上并点击垃圾桶图标即可。

手动测试

您可以直接在应用中开始使用虚构的电话号码。这样一来,您就可以在开发阶段执行手动测试,而不会遇到配额问题或受到限制。您也可以直接通过 iOS 模拟器或未安装 Google Play 服务的 Android 模拟器进行测试。

当您提供虚构电话号码并发送验证码时,系统实际上不会发送短信。作为替代,您需要提供事先配置的验证码来完成登录。

完成登录后,系统会使用该电话号码创建一位 Firebase 用户。该用户的行为和属性与真实电话号码用户相同,并且可通过同样的方式使用 Realtime Database/Cloud Firestore 和其他服务。在此过程中生成的 ID 令牌与真实电话号码用户的令牌具有相同的签名。

您还可以利用自定义声明为此类用户设置测试角色,以将其作为虚构用户区分开来(如果您想进一步限制其访问权限)。

如需手动触发 reCAPTCHA 流程以进行测试,请使用 forceRecaptchaFlowForTesting() 方法。

// Force reCAPTCHA flow
FirebaseAuth.getInstance().getFirebaseAuthSettings().forceRecaptchaFlowForTesting();

集成测试

除了手动测试外,Firebase Authentication 还提供了 API,帮助您编写用于进行电话号码身份验证测试的集成测试。这些 API 通过停用 reCAPTCHA 要求(在 Web 应用中)和静默推送通知(在 iOS 应用中)来停用应用验证。因此,您可以在这些流程中进行自动测试,并且实现起来更加容易。此外,借助这些 API,您还可以在 Android 上测试即时验证流程。

在 Android 设备上,先调用 setAppVerificationDisabledForTesting(),然后再调用 signInWithPhoneNumber。这样会自动停用应用验证,因此您无需手动解析即可传递电话号码。即使 Play Integrity 和 reCAPTCHA 都已停用,使用真实的电话号码也无法完成登录。此 API 只能使用虚构的电话号码。

// Turn off phone auth app verification.
FirebaseAuth.getInstance().getFirebaseAuthSettings()
   .setAppVerificationDisabledForTesting();

使用虚构号码调用 verifyPhoneNumber 会触发 onCodeSent 回调函数,您将需要向其提供对应的验证码。这样,您将可以在 Android 模拟器中进行测试。

Java

String phoneNum = "+16505554567";
String testVerificationCode = "123456";

// Whenever verification is triggered with the whitelisted number,
// provided it is not set for auto-retrieval, onCodeSent will be triggered.
FirebaseAuth auth = FirebaseAuth.getInstance();
PhoneAuthOptions options = PhoneAuthOptions.newBuilder(auth)
        .setPhoneNumber(phoneNum)
        .setTimeout(60L, TimeUnit.SECONDS)
        .setActivity(this)
        .setCallbacks(new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            @Override
            public void onCodeSent(@NonNull String verificationId,
                                   @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
                // Save the verification id somewhere
                // ...

                // The corresponding whitelisted code above should be used to complete sign-in.
                MainActivity.this.enableUserManuallyInputCode();
            }

            @Override
            public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
                // Sign in with the credential
                // ...
            }

            @Override
            public void onVerificationFailed(@NonNull FirebaseException e) {
                // ...
            }
        })
        .build();
PhoneAuthProvider.verifyPhoneNumber(options);

Kotlin+KTX

val phoneNum = "+16505554567"
val testVerificationCode = "123456"

// Whenever verification is triggered with the whitelisted number,
// provided it is not set for auto-retrieval, onCodeSent will be triggered.
val options = PhoneAuthOptions.newBuilder(Firebase.auth)
    .setPhoneNumber(phoneNum)
    .setTimeout(30L, TimeUnit.SECONDS)
    .setActivity(this)
    .setCallbacks(object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

        override fun onCodeSent(
            verificationId: String,
            forceResendingToken: PhoneAuthProvider.ForceResendingToken,
        ) {
            // Save the verification id somewhere
            // ...

            // The corresponding whitelisted code above should be used to complete sign-in.
            this@MainActivity.enableUserManuallyInputCode()
        }

        override fun onVerificationCompleted(phoneAuthCredential: PhoneAuthCredential) {
            // Sign in with the credential
            // ...
        }

        override fun onVerificationFailed(e: FirebaseException) {
            // ...
        }
    })
    .build()
PhoneAuthProvider.verifyPhoneNumber(options)

此外,您可以在 Android 中测试自动检索流程,只需调用 setAutoRetrievedSmsCodeForPhoneNumber 方法,为自动检索设置虚构号码及其对应的验证码即可。

调用 verifyPhoneNumber 方法时,它会直接使用 PhoneAuthCredential 触发 onVerificationCompleted 方法。这仅适用于虚构的电话号码。

将您的应用发布到 Google Play 商店时,请确保此验证已停用,并且没有将虚构电话号码硬编码到您的应用中。

Java

// The test phone number and code should be whitelisted in the console.
String phoneNumber = "+16505554567";
String smsCode = "123456";

FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
FirebaseAuthSettings firebaseAuthSettings = firebaseAuth.getFirebaseAuthSettings();

// Configure faking the auto-retrieval with the whitelisted numbers.
firebaseAuthSettings.setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode);

PhoneAuthOptions options = PhoneAuthOptions.newBuilder(firebaseAuth)
        .setPhoneNumber(phoneNumber)
        .setTimeout(60L, TimeUnit.SECONDS)
        .setActivity(this)
        .setCallbacks(new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            @Override
            public void onVerificationCompleted(@NonNull PhoneAuthCredential credential) {
                // Instant verification is applied and a credential is directly returned.
                // ...
            }

            // ...
        })
        .build();
PhoneAuthProvider.verifyPhoneNumber(options);

Kotlin+KTX

// The test phone number and code should be whitelisted in the console.
val phoneNumber = "+16505554567"
val smsCode = "123456"

val firebaseAuth = Firebase.auth
val firebaseAuthSettings = firebaseAuth.firebaseAuthSettings

// Configure faking the auto-retrieval with the whitelisted numbers.
firebaseAuthSettings.setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode)

val options = PhoneAuthOptions.newBuilder(firebaseAuth)
    .setPhoneNumber(phoneNumber)
    .setTimeout(60L, TimeUnit.SECONDS)
    .setActivity(this)
    .setCallbacks(object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        override fun onVerificationCompleted(credential: PhoneAuthCredential) {
            // Instant verification is applied and a credential is directly returned.
            // ...
        }

        // ...
    })
    .build()
PhoneAuthProvider.verifyPhoneNumber(options)

后续步骤

在用户首次登录后,系统会创建一个新的用户帐号,并将其与该用户登录时使用的凭据(即用户名和密码、电话号码或者身份验证提供方信息)相关联。此新帐号存储在您的 Firebase 项目中,无论用户采用何种方式登录,您项目中的每个应用都可以使用此帐号来识别用户。

  • 在您的应用中,您可以从 FirebaseUser 对象获取用户的基本个人资料信息。请参阅管理用户

  • 在您的 Firebase Realtime Database 和 Cloud Storage 安全规则中,您可以从 auth 变量获取已登录用户的唯一用户 ID,然后利用此 ID 来控制用户可以访问哪些数据。

您可以将多个身份验证提供方凭据与一个现有用户帐号关联,让用户可以使用多个身份验证提供方登录您的应用。

如需将用户退出登录,请调用 signOut

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();