Google 致力于为黑人社区推动种族平等。查看具体举措

使用电话号码和 C++ 向 Firebase 进行身份验证

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

您可以使用 Firebase 身份验证通过向用户手机发送 SMS 消息来登录用户。用户使用 SMS 消息中包含的一次性代码登录。

本文档介绍如何使用 Firebase SDK 实现电话号码登录流程。

在你开始之前

  1. 将 Firebase 添加到您的 C++ 项目中。
  2. 如果您尚未将应用连接到 Firebase 项目,请从Firebase 控制台执行此操作。

在 Apple 平台上,请注意电话号码登录需要物理设备,并且无法在模拟器上运行。

安全问题

仅使用电话号码的身份验证虽然方便,但不如其他可用方法安全,因为电话号码的拥有可以在用户之间轻松转移。此外,在具有多个用户配置文件的设备上,任何可以接收 SMS 消息的用户都可以使用设备的电话号码登录帐户。

如果您在应用程序中使用基于电话号码的登录,则应将其与更安全的登录方法一起提供,并告知用户使用电话号码登录的安全权衡。

为您的 Firebase 项目启用电话号码登录

要通过短信登录用户,您必须首先为您的 Firebase 项目启用电话号码登录方法:

  1. Firebase 控制台中,打开身份验证部分。
  2. 登录方式页面,启用电话号码登录方式。

Firebase 的电话号码登录请求配额足够高,大多数应用不会受到影响。但是,如果您需要使用电话身份验证登录大量用户,则可能需要升级您的定价计划。请参阅定价页面。

开始接收 APNs 通知(Apple 平台)

要在 Apple 平台上使用电话号码身份验证,您的应用必须能够接收来自 Firebase 的 APNs 通知。当您首次在设备上使用用户的电话号码登录用户时,Firebase 身份验证会向设备发送静默推送通知,以验证电话号码登录请求是否来自您的应用。 (因此,无法在模拟器上使用电话号码登录。)

要启用 APNs 通知以用于 Firebase 身份验证:

  1. 在 Xcode 中,为您的项目启用推送通知
  2. 将您的 APNs 证书上传到 Firebase。如果您还没有 APNs 证书,请确保在Apple Developer Member Center中创建一个。

    1. 在 Firebase 控制台的项目中,选择齿轮图标,选择Project Settings ,然后选择Cloud Messaging选项卡。

    2. 为您的开发证书、生产证书或两者选择上传证书按钮。至少需要一个。

    3. 对于每个证书,选择 .p12 文件,并提供密码(如果有)。确保此证书的捆绑包 ID 与您的应用的捆绑包 ID 匹配。选择保存

向用户手机发送验证码

要启动电话号码登录,请向用户显示一个界面,提示他们提供电话号码,然后调用PhoneAuthProvider::VerifyPhoneNumber以请求 Firebase 通过 SMS 向用户的手机发送验证码:

  1. 获取用户的电话号码。

    法律要求各不相同,但作为最佳实践并为您的用户设定期望,您应该告知他们,如果他们使用电话登录,他们可能会收到一条短信进行验证,并适用标准费率。

  2. 调用PhoneAuthProvider::VerifyPhoneNumber ,将用户的电话号码传递给它。
    class PhoneListener : public PhoneAuthProvider::Listener {
     public:
      ~PhoneListener() override {}
    
      void OnVerificationCompleted(Credential credential) override {
        // Auto-sms-retrieval or instant validation has succeeded (Android only).
        // No need for the user to input the verification code manually.
        // `credential` can be used instead of calling GetCredential().
      }
    
      void OnVerificationFailed(const std::string& error) override {
        // Verification code not sent.
      }
    
      void OnCodeSent(const std::string& verification_id,
                      const PhoneAuthProvider::ForceResendingToken&
                          force_resending_token) override {
        // Verification code successfully sent via SMS.
        // Show the Screen to enter the Code.
        // Developer may want to save that verification_id along with other app states in case
        // the app is terminated before the user gets the SMS verification code.
      }
    };
    
    PhoneListener phone_listener;
    PhoneAuthProvider& phone_provider = PhoneAuthProvider::GetInstance(auth);
    phone_provider->VerifyPhoneNumber(phone_number, kAutoVerifyTimeOut, null,
                                      &phone_listener);
    
    当你调用PhoneAuthProvider::VerifyPhoneNumber ,Firebase,
    • (在 iOS 上)向您的应用发送静默推送通知,
    • 向指定的电话号码发送包含验证码的 SMS 消息,并将验证 ID 传递给您的完成函数。您将需要验证码和验证 ID 才能登录用户。
  3. 保存验证 ID 并在您的应用加载时恢复它。通过这样做,如果您的应用在用户完成登录流程之前终止(例如,在切换到 SMS 应用时),您可以确保您仍然拥有有效的验证 ID。

    您可以以任何方式保留验证 ID。如果您使用跨平台 C++ 框架编写,它应该提供应用程序终止和恢复的通知。在这些事件中,您可以分别保存和恢复验证 ID。

如果对VerifyPhoneNumber的调用导致在侦听器上调用OnCodeSent ,您可以在用户在 SMS 消息中收到验证码时提示他们输入验证码。

另一方面,如果对VerifyPhoneNumber的调用导致OnVerificationCompleted ,则自动验证已成功,您现在将拥有一个可以使用的Credential ,如下所述。

使用验证码登录用户

在用户向您的应用提供 SMS 消息中的验证码后,通过从验证码和验证 ID 创建一个Credential对象并将该对象传递给Auth::SignInWithCredential来登录用户。

  1. 从用户那里获取验证码。
  2. 从验证码和验证 ID 创建一个Credential对象。
    Credential credential = phone_auth_provider->GetCredential(
        verification_id_.c_str(), verification_code.c_str());
        
  3. 使用Credential对象登录用户:
    Future<User*> future = auth_->SignInWithCredential(credential);
    future.OnCompletion(
        [](const Future<User*>& result, void*) {
          if (result.error() == kAuthErrorNone) {
            // Successful.
            // User is signed in.
            const User* user = *result.result();
    
            // This should display the phone number.
            printf("Phone number: %s", user->phone_number().c_str());
    
            // The phone number provider UID is the phone number itself.
            printf("Phone provider uid: %s", user->uid().c_str());
    
            // The phone number providerID is 'phone'
            printf("Phone provider ID: %s", user->provider_id().c_str());
          } else {
            // Error.
            printf("Sign in error: %s", result.error_message().c_str());
          }
        },
        nullptr);
    

下一步

用户首次登录后,会创建一个新用户帐户并将其链接到凭据(即用户名和密码、电话号码或身份验证提供商信息),即用户登录时使用的凭据。这个新帐户作为 Firebase 项目的一部分存储,可用于在项目中的每个应用中识别用户,无论用户如何登录。

  • 在您的应用程序中,您可以从firebase::auth::User对象获取用户的基本个人资料信息:

    firebase::auth::User* user = auth->current_user();
    if (user != nullptr) {
      std::string name = user->display_name();
      std::string email = user->email();
      std::string photo_url = user->photo_url();
      // The user's ID, unique to the Firebase project.
      // Do NOT use this value to authenticate with your backend server,
      // if you have one. Use firebase::auth::User::Token() instead.
      std::string uid = user->uid();
    }
    
  • 在您的 Firebase 实时数据库和云存储安全规则中,您可以从auth变量中获取登录用户的唯一用户 ID,并使用它来控制用户可以访问哪些数据。

您可以通过将身份验证提供程序凭据链接到现有用户帐户来允许用户使用多个身份验证提供程序登录您的应用程序。

要注销用户,请调用SignOut()

auth->SignOut();