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

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

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

准备工作

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

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

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

安全考量

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

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

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

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

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

开始接收 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) =&gt {
        // 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) =&gt {
        // The verification code was not sent.
        // `error` contains a human readable explanation of the problem.
      },
      codeSent: (id, token) =&gt {
        // 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) =&gt {
        // 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 =&gt {
      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 DatabaseCloud Storage 安全规则中,您可以从 auth 变量获取已登录用户的唯一用户 ID,然后利用此 ID 来控制用户可以访问哪些数据。

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

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

auth.SignOut();