使用 JavaScript 通過電話號碼進行 Firebase 身份驗證

您可以使用 Firebase 身份驗證通過向用戶的手機發送 SMS 消息來登錄用戶。用戶使用 SMS 消息中包含的一次性代碼登錄。

最簡單的方法來添加電話號碼,登錄到您的應用程序是使用FirebaseUI ,其中包括一個下拉在登錄窗口小部件實現簽到流的電話號碼登錄,以及基於密碼的和聯合的標誌-在。本文檔介紹瞭如何使用 Firebase SDK 實現電話號碼登錄流程。

在你開始之前

如果你還沒有準備好,從初始化片段複製火力地堡控制台到您的項目中所述添加火力地堡到你的JavaScript項目

安全問題

僅使用電話號碼的身份驗證雖然方便,但不如其他可用方法安全,因為電話號碼的所有權很容易在用戶之間轉移。此外,在具有多個用戶配置文件的設備上,任何可以接收 SMS 消息的用戶都可以使用設備的電話號碼登錄帳戶。

如果您在應用中使用基於電話號碼的登錄,則應將其與更安全的登錄方法一起提供,並告知用戶使用電話號碼登錄的安全性權衡。

為您的 Firebase 項目啟用電話號碼登錄

要通過短信登錄用戶,您必須首先為 Firebase 項目啟用電話號碼登錄方法:

  1. 火力地堡控制台,打開驗證部分。
  2. 登錄方法頁,使電話號碼登錄方法。
  3. 在同一頁上,如果將承載您的應用程序的域名並沒有在OAuth重定向域部分列出,添加您的域名。

Firebase 的電話號碼登錄請求配額足夠高,大多數應用不會受到影響。但是,如果您需要使用電話身份驗證登錄大量用戶,則可能需要升級定價計劃。請參閱定價頁面。

設置 reCAPTCHA 驗證器

在您可以使用電話號碼登錄用戶之前,您必須設置 Firebase 的 reCAPTCHA 驗證程序。 Firebase 使用 reCAPTCHA 來防止濫用,例如確保電話號碼驗證請求來自您的應用允許的域之一。

您無需手動設置 reCAPTCHA 客戶端;當您使用火力地堡SDK的RecaptchaVerifier對象,火力地堡自動創建和處理所有必要的客戶端密鑰和秘密。

所述RecaptchaVerifier對象支持隱形驗證碼,這往往可以驗證用戶,而無需任何用戶動作,以及所述reCAPTCHA小工具,它總是需要用戶交互成功完成。

通過在呈現 reCAPTCHA 之前更新 Auth 實例上的語言代碼,可以將底層呈現的 reCAPTCHA 本地化為用戶的偏好。上述本地化也將適用於發送給用戶的 SMS 消息,其中包含驗證碼。

網頁版 9

import { getAuth } from "firebase/auth";

const auth = getAuth();
auth.languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();

網頁版 8

firebase.auth().languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();

使用隱形 reCAPTCHA

要使用一種無形的驗證碼,創建一個RecaptchaVerifier與物體size參數設置為invisible ,指定提交您的登錄表單按鈕的ID。例如:

網頁版 9

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier('sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
}, auth);

網頁版 8

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

使用 reCAPTCHA 小部件

要使用可視reCAPTCHA小工具,您的網頁上創建一個元素包含小部件,然後創建一個RecaptchaVerifier對象,指定容器的ID,當你這樣做。例如:

網頁版 9

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier('recaptcha-container', {}, auth);

網頁版 8

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');

可選:指定 reCAPTCHA 參數

您可以選擇設置的回調函數RecaptchaVerifier當用戶解決了驗證碼或驗證碼的用戶提交表單到期之前稱為對象:

網頁版 9

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier('recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
}, auth);

網頁版 8

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

可選:預渲染 reCAPTCHA

如果你想在提交登錄請求之前預渲染的驗證碼,呼叫render

網頁版 9

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

網頁版 8

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

經過render結算時,你得到的reCAPTCHA控件ID,您可以使用,使該電話的reCAPTCHA API:

網頁版 9

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

網頁版 8

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

向用戶手機發送驗證碼

要啟動手機號碼登錄,顯示用戶界面,提示他們提供他們的電話號碼,然後打電話signInWithPhoneNumber到請求火力地堡通過短信發送驗證碼到用戶的手機:

  1. 獲取用戶的電話號碼。

    法律要求各不相同,但作為最佳實踐並為您的用戶設定期望,您應該通知他們,如果他們使用電話登錄,他們可能會收到一條 SMS 消息進行驗證,並且適用標準費率。

  2. 呼叫signInWithPhoneNumber ,將其傳遞給用戶的電話號碼和RecaptchaVerifier前面創建。

    網頁版 9

    import { getAuth, signInWithPhoneNumber } from "firebase/auth";
    
    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    
    const auth = getAuth();
    signInWithPhoneNumber(auth, phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });

    網頁版 8

    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });
    如果signInWithPhoneNumber導致錯誤,重設驗證碼,所以用戶可以再試一次:
    grecaptcha.reset(window.recaptchaWidgetId);
    
    // Or, if you haven't stored the widget ID:
    window.recaptchaVerifier.render().then(function(widgetId) {
      grecaptcha.reset(widgetId);
    }
    

signInWithPhoneNumber方法問題reCAPTCHA驗證碼給用戶,如果用戶通過了挑戰,要求將火力地堡驗證發送一條包含驗證碼到用戶的手機短信。

使用驗證碼登錄用戶

在調用後signInWithPhoneNumber成功,則提示用戶輸入他們通過SMS接收到的驗證碼。然後,符號在由代碼傳遞給所述用戶confirm所述的方法ConfirmationResult傳遞給對象signInWithPhoneNumber的履行處理程序(即,其then塊)。例如:

網頁版 9

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

網頁版 8

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

如果調用confirm成功,用戶成功登錄。

獲取中間 AuthCredential 對象

如果你需要得到一個AuthCredential為用戶的帳戶對象,通過從確認結果的驗證碼和驗證碼PhoneAuthProvider.credential而不是調用confirm

var credential = firebase.auth.PhoneAuthProvider.credential(confirmationResult.verificationId, code);

然後,您可以使用憑據登錄用戶:

firebase.auth().signInWithCredential(credential);

使用虛構的電話號碼進行測試

您可以通過 Firebase 控制台為開發設置虛構的電話號碼。使用虛構的電話號碼進行測試具有以下好處:

  • 在不消耗您的使用配額的情況下測試電話號碼身份驗證。
  • 在不發送實際 SMS 消息的情況下測試電話號碼身份驗證。
  • 使用相同的電話號碼運行連續測試而不會受到限制。如果審閱者碰巧使用相同的電話號碼進行測試,這可以最大限度地降低 App Store 審閱過程中被拒絕的風險。
  • 無需任何額外工作即可在開發環境中輕鬆測試,例如無需 Google Play 服務即可在 iOS 模擬器或 Android 模擬器中進行開發的能力。
  • 編寫集成測試,而不會被生產環境中通常應用於真實電話號碼的安全檢查所阻止。

虛構的電話號碼必須滿足以下要求:

  1. 確保您使用的電話號碼確實是虛構的,並且不存在。 Firebase 身份驗證不允許您將真實用戶使用的現有電話號碼設置為測試號碼。一種選擇是使用555前綴號碼作為美國測試的電話號碼,例如:+1 650-555-3434
  2. 電話號碼的格式必須正確以適應長度和其他限制。他們仍將通過與真實用戶電話號碼相同的驗證。
  3. 您最多可以添加 10 個電話號碼進行開發。
  4. 使用難以猜測的測試電話號碼/代碼並經常更改它們。

創建虛構的電話號碼和驗證碼

  1. 火力地堡控制台,打開驗證部分。
  2. 在登錄方法選項卡,使手機供應商,如果你還沒有準備好。
  3. 打開進行測試手風琴菜單的電話號碼
  4. 提供要測試的電話號碼,例如:+1 650-555-3434。
  5. 提供一種用於特定數目的6位數驗證碼,例如:654321。
  6. 添加的數量。如果需要,您可以通過將鼠標懸停在相應行上並單擊垃圾桶圖標來刪除電話號碼及其代碼。

手動測試

您可以直接開始在您的應用程序中使用虛構的電話號碼。這使您可以在開發階段執行手動測試,而不會遇到配額問題或限制。您還可以在未安裝 Google Play 服務的情況下直接從 iOS 模擬器或 Android 模擬器進行測試。

當您提供虛構的電話號碼並發送驗證碼時,不會發送實際的 SMS。相反,您需要提供之前配置的驗證碼才能完成登錄。

登錄完成後,會使用該電話號碼創建 Firebase 用戶。用戶具有與真實電話號碼用戶相同的行為和屬性,並且可以以相同的方式訪問實時數據庫/Cloud Firestore 和其他服務。在此過程中鑄造的 ID 令牌具有與真實電話號碼用戶相同的簽名。

另一種選擇是設置一個測試角色通過自定義的權利要求對這些用戶他們區分假冒的用戶,如果你想進一步限制訪問。

集成測試

除了手動測試之外,Firebase 身份驗證還提供 API 來幫助編寫電話身份驗證測試的集成測試。這些 API 通過禁用 Web 中的 reCAPTCHA 要求和 iOS 中的靜默推送通知來禁用應用驗證。這使得在這些流程中進行自動化測試成為可能並且更容易實現。此外,它們有助於提供在 Android 上測試即時驗證流程的能力。

在網頁上,集appVerificationDisabledForTestingtrue呈現前firebase.auth.RecaptchaVerifier 。這會自動解析 reCAPTCHA,讓您無需手動解析即可傳遞電話號碼。請注意,即使禁用了 reCAPTCHA,使用非虛構電話號碼仍無法完成登錄。此 API 只能使用虛構電話號碼。

// Turn off phone auth app verification.
firebase.auth().settings.appVerificationDisabledForTesting = true;

var phoneNumber = "+16505554567";
var testVerificationCode = "123456";

// This will render a fake reCAPTCHA as appVerificationDisabledForTesting is true.
// This will resolve after rendering without app verification.
var appVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
// signInWithPhoneNumber will call appVerifier.verify() which will resolve with a fake
// reCAPTCHA response.
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
    .then(function (confirmationResult) {
      // confirmationResult can resolve with the fictional testVerificationCode above.
      return confirmationResult.confirm(testVerificationCode)
    }).catch(function (error) {
      // Error; SMS not sent
      // ...
    });

當應用驗證被禁用時,可見和不可見的模擬 reCAPTCHA 應用驗證器的行為不同:

  • 可見驗證碼:當可見光驗證碼經由呈現appVerifier.render()它會自動第二延遲的一小部分後自行解決。這相當於用戶在渲染時立即單擊 reCAPTCHA。 reCAPTCHA 響應將在一段時間後過期,然後再次自動解決。
  • 隱形驗證碼:看不見驗證碼不上渲染未自動解析和對代替這樣做appVerifier.verify()調用或當第二延遲的一小部分後,點擊驗證碼的按鈕錨。同樣,響應將在一段時間後到期,才會自動議決後appVerifier.verify()調用或點擊驗證碼的按鈕錨時一次。

每當模擬 reCAPTCHA 被解析時,相應的回調函數就會按預期與假響應一起觸發。如果還指定了到期回調,它將在到期時觸發。

下一步

用戶首次登錄後,將創建一個新用戶帳戶並將其鏈接到用戶登錄時使用的憑據(即用戶名和密碼、電話號碼或身份驗證提供商信息)。這個新帳戶作為 Firebase 項目的一部分存儲,可用於識別項目中每個應用中的用戶,無論用戶如何登錄。

  • 在您的應用程序,要知道你的用戶的身份驗證狀態的推薦方法是設置一個觀察者的Auth的對象。然後,您可以從用戶的基本個人資料信息User對象。請參閱管理用戶

  • 在你的火力地堡實時數據庫和雲存儲安全規則,你可以得到簽署的,從用戶的唯一的用戶ID auth的變量,並用它來控制哪些數據的用戶可以訪問。

您可以允許用戶通過使用多個身份驗證提供登錄到您的應用程序連接身份驗證提供憑據到現有的用戶帳戶。

要註銷用戶,請撥打signOut

網頁版 9

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

網頁版 8

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});