電話驗證功能

電話驗證可讓使用者以手機做為驗證器登入 Firebase。系統會使用提供的電話號碼傳送簡訊給使用者,內含專屬驗證碼。授權代碼後,使用者就能登入 Firebase。

使用者提供的電話號碼會傳送給 Google 並儲存,以改善 Google 服務 (包括但不限於 Firebase) 的垃圾內容和濫用行為防範機制。開發人員應確保在使用 Firebase Authentication 電話號碼登入服務前,已取得適當的消費者同意聲明。

Firebase 電話驗證功能僅適用於部分國家/地區。詳情請參閱他們的常見問題

設定

開始使用手機驗證前,請先完成下列步驟:

  1. Firebase 控制台中啟用「電話」做為登入方式。
  2. Android:如果您尚未在 Firebase 控制台中設定應用程式的 SHA-1 雜湊,請進行設定。 如要瞭解如何找出應用程式的 SHA-1 雜湊,請參閱「驗證用戶端」。
  3. iOS:在 Xcode 中為專案啟用推播通知,並確保 APNs 驗證金鑰已透過 Firebase 雲端通訊 (FCM) 設定。此外,您必須啟用遠端通知的背景模式。如需這個步驟的詳細說明,請參閱 Firebase iOS 電話號碼驗證說明文件。
  4. 網頁:請確認您已在 Firebase 主控台的「OAuth redirect domains」(OAuth 重新導向網域) 下方新增應用程式網域。

注意:電話號碼登入功能僅適用於實體裝置和網頁。如要在裝置模擬器上測試驗證流程,請參閱「測試」一節。

用量

Flutter 專用的 Firebase 驗證 SDK 提供兩種方式,讓使用者透過電話號碼登入。與網頁不同,原生 (例如 Android 和 iOS) 平台提供不同的電話號碼驗證功能,因此每個平台都有專屬的驗證方法:

  • 原生平台verifyPhoneNumber
  • 網路平台signInWithPhoneNumber

原生:verifyPhoneNumber

在原生平台上,使用者必須先驗證電話號碼,然後才能登入或將帳戶連結至 PhoneAuthCredential

您必須先提示使用者提供電話號碼,提供後,請呼叫 verifyPhoneNumber() 方法:

await FirebaseAuth.instance.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) {},
  verificationFailed: (FirebaseAuthException e) {},
  codeSent: (String verificationId, int? resendToken) {},
  codeAutoRetrievalTimeout: (String verificationId) {},
);

您必須處理 4 個不同的回呼,每個回呼都會決定如何更新應用程式 UI:

  1. verificationCompleted:在 Android 裝置上自動處理簡訊驗證碼。
  2. verificationFailed:處理失敗事件,例如電話號碼無效或超出簡訊配額。
  3. codeSent:處理 Firebase 將驗證碼傳送至裝置的情況,並提示使用者輸入驗證碼。
  4. codeAutoRetrievalTimeout:處理自動處理簡訊驗證碼失敗時的逾時情況。

verificationCompleted

只有支援自動解析簡訊驗證碼的 Android 裝置,才會呼叫這個處理常式。

Android 裝置收到簡訊驗證碼後,系統會自動驗證,使用者不必手動輸入。如果發生這個事件,系統會自動提供 PhoneAuthCredential,可用於登入或連結使用者的電話號碼。

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) async {
    // ANDROID ONLY!

    // Sign the user in (or link) with the auto-generated credential
    await auth.signInWithCredential(credential);
  },
);

verificationFailed

如果 Firebase 傳回錯誤 (例如電話號碼有誤,或是專案的簡訊配額已用盡),系統會將 FirebaseAuthException 傳送至這個處理常式。在這種情況下,您會根據錯誤代碼,提示使用者發生錯誤。

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationFailed: (FirebaseAuthException e) {
    if (e.code == 'invalid-phone-number') {
      print('The provided phone number is not valid.');
    }

    // Handle other errors
  },
);

codeSent

當 Firebase 將簡訊驗證碼傳送至裝置時,系統會使用 verificationIdresendToken 觸發這個處理常式 (Android 裝置一律會傳回 null 值,只有 Android 裝置支援 resendToken)。

觸發後,建議您更新應用程式 UI,提示使用者輸入預期的簡訊驗證碼。輸入簡訊驗證碼後,即可將驗證 ID 與簡訊驗證碼合併,建立新的 PhoneAuthCredential

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  codeSent: (String verificationId, int? resendToken) async {
    // Update the UI - wait for the user to enter the SMS code
    String smsCode = 'xxxx';

    // Create a PhoneAuthCredential with the code
    PhoneAuthCredential credential = PhoneAuthProvider.credential(verificationId: verificationId, smsCode: smsCode);

    // Sign the user in (or link) with the credential
    await auth.signInWithCredential(credential);
  },
);

根據預設,如果 Firebase 最近已傳送新的簡訊,就不會再次傳送。不過,您可以將重新傳送權杖傳遞至 forceResendingToken 引數,再次呼叫 verifyPhoneNumber 方法來覆寫這項行為。如果成功,系統會重新傳送簡訊。

codeAutoRetrievalTimeout

如果 Android 裝置支援自動解析簡訊驗證碼,且裝置未在特定時間範圍內自動解析簡訊,系統就會呼叫這個處理常式。時間一到,裝置就不會再嘗試解決任何傳入的訊息。

裝置預設會等待 30 秒,但您可以使用 timeout 引數自訂這項設定:

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  timeout: const Duration(seconds: 60),
  codeAutoRetrievalTimeout: (String verificationId) {
    // Auto-resolution timed out...
  },
);

網頁:signInWithPhoneNumber

在網頁平台上,使用者可以輸入傳送至指定電話號碼的簡訊代碼,確認自己有權存取該手機,藉此登入帳戶。 為提升安全性及防範垃圾內容,系統會要求使用者完成 Google reCAPTCHA 小工具,證明自己是人類。確認後,系統會傳送簡訊驗證碼。

Flutter 適用的 Firebase 驗證 SDK 預設會管理 reCAPTCHA 小工具,但如有需要,您也可以控管小工具的顯示方式和設定。如要開始使用,請使用電話號碼呼叫 signInWithPhoneNumber 方法。

FirebaseAuth auth = FirebaseAuth.instance;

// Wait for the user to complete the reCAPTCHA & for an SMS code to be sent.
ConfirmationResult confirmationResult = await auth.signInWithPhoneNumber('+44 7123 123 456');

呼叫這個方法時,系統會先觸發顯示 reCAPTCHA 小工具。使用者必須先完成測試,系統才會傳送簡訊驗證碼。完成後,您就可以在已解析的 ConfirmationResult 回應中,將簡訊代碼提供給 confirm 方法,讓使用者登入:

UserCredential userCredential = await confirmationResult.confirm('123456');

與其他登入流程一樣,成功登入會觸發您在整個應用程式中訂閱的所有驗證狀態監聽器。

reCAPTCHA 設定

reCAPTCHA 小工具是全代管流程,可為您的網路應用程式提供安全防護。

signInWithPhoneNumber 的第二個引數接受選用的 RecaptchaVerifier 執行個體,可用於管理小工具。系統預設會在觸發登入流程時,將小工具算繪為隱形小工具。 「隱形」小工具會以全頁模式顯示在應用程式頂端。

不過,您可以顯示內嵌小工具,使用者必須明確按下該小工具才能驗證身分。

如要新增內嵌小工具,請在 RecaptchaVerifier 執行個體的 container 引數中指定 DOM 元素 ID。 元素必須存在且為空白,否則會擲回錯誤。 如果未提供 container 引數,小工具會以「隱形」狀態顯示。

ConfirmationResult confirmationResult = await auth.signInWithPhoneNumber('+44 7123 123 456', RecaptchaVerifier(
  container: 'recaptcha',
  size: RecaptchaVerifierSize.compact,
  theme: RecaptchaVerifierTheme.dark,
));

您可以視需要自訂 sizetheme 引數,變更大小和主題,如上所示。

您也可以監聽事件,例如使用者是否已完成 reCAPTCHA、reCAPTCHA 是否已過期,或是否擲回錯誤:

RecaptchaVerifier(
  onSuccess: () => print('reCAPTCHA Completed!'),
  onError: (FirebaseAuthException error) => print(error),
  onExpired: () => print('reCAPTCHA Expired!'),
);

測試

Firebase 支援在本機測試電話號碼:

  1. 在 Firebase 控制台中,選取「電話」驗證供應商,然後按一下「用於測試的電話號碼」下拉式選單。
  2. 輸入新的電話號碼 (例如 +44 7444 555666) 和測試代碼 (例如 123456)。

如果為 verifyPhoneNumbersignInWithPhoneNumber 方法提供測試電話號碼,系統不會實際傳送簡訊。您可以改為直接將測試程式碼提供給 PhoneAuthProvider,或透過 signInWithPhoneNumber 的確認結果處理常式提供。