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

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

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

准备工作

  1. 您必须先将 Firebase Unity SDK(具体而言就是 FirebaseAuth.unitypackage)添加至您的 Unity 项目中,然后才能使用 Firebase Authentication

    如需这些初始设置步骤的详细说明,请参阅将 Firebase 添加到您的 Unity 项目

  2. 如果您尚未将您的应用与 Firebase 项目关联,请在 Firebase 控制台中进行关联。
  3. 了解电话号码登录的平台要求:
    • 电话号码登录仅适用于移动平台。
    • iOS 系统需要实体设备才能实现电话号码登录,在模拟器上无法实现此功能。

安全考量

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

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

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

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

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

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

开始接收 APNs 通知(仅限 iOS)

如需在 iOS 系统上使用电话号码身份验证,您的应用必须能够接收来自 Firebase 的 APNs 通知。当用户首次在设备上通过电话号码登录时,Firebase Authentication 会向设备发送一条静默推送通知,以验证电话号码登录请求是否来自您的应用。因此,您无法在模拟器上使用电话号码登录。

启用 APNs 通知以用于 Firebase Authentication:

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

    1. 在 Firebase 控制台中,在您的项目内依次选择齿轮图标、项目设置以及 Cloud Messaging 标签页。

    2. 选择开发证书和/或生产证书对应的上传证书按钮。二者至少需要选择其一。

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

向用户的电话发送验证码

如需启动电话号码登录,请向用户显示一个提示其输入电话号码的界面,然后调用 PhoneAuthProvider.VerifyPhoneNumber 以请求 Firebase 通过短信向用户电话发送身份验证码:

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

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

  2. 调用 PhoneAuthProvider.VerifyPhoneNumber,并向其传递包含用户电话号码的 PhoneAuthOptions。
    PhoneAuthProvider provider = PhoneAuthProvider.GetInstance(firebaseAuth);
    provider.VerifyPhoneNumber(
      new Firebase.Auth.PhoneAuthOptions {
        PhoneNumber = phoneNumber,
        TimeoutInMilliseconds = phoneAuthTimeoutMs,
        ForceResendingToken = null
      },
      verificationCompleted: (credential) => {
        // Auto-sms-retrieval or instant validation has succeeded (Android only).
        // There is no need to input the verification code.
        // `credential` can be used instead of calling GetCredential().
      },
      verificationFailed: (error) => {
        // The verification code was not sent.
        // `error` contains a human readable explanation of the problem.
      },
      codeSent: (id, token) => {
        // Verification code was successfully sent via SMS.
        // `id` contains the verification id that will need to passed in with
        // the code from the user when calling GetCredential().
        // `token` can be used if the user requests the code be sent again, to
        // tie the two requests together.
      },
      codeAutoRetrievalTimeout: (id) => {
        // Called when the auto-sms-retrieval has timed out, based on the given
        // timeout parameter.
        // `id` contains the verification id of the request that timed out.
      });
    
    当您调用 PhoneAuthProvider.VerifyPhoneNumber 时,Firebase 将
    • (在 iOS 系统上)向您的应用发送一条静默推送通知。
    • Firebase 会向指定的电话号码发送一条包含验证码的短信,并将验证 ID 传递给您的完成函数。验证码和验证 ID 要同时具备,用户才能登录。
  3. 保存验证 ID,并在应用加载时将其还原。这样可确保即使您的应用在用户完成登录流程之前被终止(例如,用户切换到短信应用时),您仍然保留有效的验证 ID。

    您可以用任何方式留存验证 ID。其中一种简单的方法就是使用 UnityEngine.PlayerPrefs 保存验证 ID。

如果传递至 codeSent 的回调函数被调用,那么您可以在用户收到验证码短信时提示用户输入验证码。

另一方面,如果 verificationCompleted 的回调函数被调用,则表示自动验证成功,您现在便拥有了 PhoneAuthCredential,请按下文所述的方式使用。

使用验证码让用户登录

用户将短信中的验证码提供给您的应用之后,系统会根据验证码和验证 ID 创建一个 PhoneAuthCredential 对象并将此对象传递给 FirebaseAuth.SignInAndRetrieveDataWithCredentialAsync,以便让用户登录。

  1. 从用户处获取验证码。
  2. 根据验证码和验证 ID 创建 Credential 对象。
    PhoneAuthCredential credential =
        phoneAuthProvider.GetCredential(verificationId, verificationCode);
        
  3. 使用 PhoneAuthCredential 对象让用户登录:
    auth.SignInAndRetrieveDataWithCredentialAsync(credential).ContinueWith(task => {
      if (task.IsFaulted) {
        Debug.LogError("SignInAndRetrieveDataWithCredentialAsync encountered an error: " +
                       task.Exception);
        return;
      }
    
      FirebaseUser newUser = task.Result.User;
      Debug.Log("User signed in successfully");
      // This should display the phone number.
      Debug.Log("Phone number: " + newUser.PhoneNumber);
      // The phone number providerID is 'phone'.
      Debug.Log("Phone provider ID: " + newUser.ProviderId);
    });
    

后续步骤

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

  • 在您的应用中,您可以从 Firebase.Auth.FirebaseUser 对象获取用户的基本个人资料信息:

    Firebase.Auth.FirebaseUser user = auth.CurrentUser;
    if (user != null) {
      string name = user.DisplayName;
      string email = user.Email;
      System.Uri photo_url = user.PhotoUrl;
      // 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 User.TokenAsync() instead.
      string uid = user.UserId;
    }
    
  • 在您的 Firebase Realtime Database 和 Cloud Storage 安全规则中,您可以从 auth 变量获取已登录用户的唯一用户 ID,然后利用此 ID 来控制用户可以访问哪些数据。

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

如需将用户退出登录,请调用 SignOut()

auth.SignOut();