您可以使用 Firebase 身份驗證通過向用戶的手機發送短信來登錄用戶。用戶使用 SMS 消息中包含的一次性代碼登錄。
將電話號碼登錄添加到您的應用程序的最簡單方法是使用FirebaseUI ,它包括一個插入式登錄小部件,該小部件實現電話號碼登錄的登錄流程,以及基於密碼和聯合登錄-在。本文檔介紹瞭如何使用 Firebase SDK 實現電話號碼登錄流程。
在你開始之前
如果您還沒有,請將初始化片段從Firebase 控制台複製到您的項目,如將 Firebase 添加到您的 JavaScript 項目中所述。安全問題
僅使用電話號碼進行身份驗證雖然方便,但不如其他可用方法安全,因為電話號碼的所有權可以在用戶之間輕鬆轉移。此外,在具有多個用戶配置文件的設備上,任何可以接收 SMS 消息的用戶都可以使用設備的電話號碼登錄帳戶。
如果您在您的應用中使用基於電話號碼的登錄,您應該將其與更安全的登錄方法一起提供,並告知用戶使用電話號碼登錄的安全權衡。
為您的 Firebase 項目啟用電話號碼登錄
要通過短信登錄用戶,您必須首先為您的 Firebase 項目啟用電話號碼登錄方法:
- 在Firebase 控制台中,打開身份驗證部分。
- 在登錄方法頁面上,啟用電話號碼登錄方法。
- 在同一頁面上,如果將託管您的應用程序的域未在OAuth 重定向域部分中列出,請添加您的域。
Firebase 的電話號碼登錄請求配額足夠高,大多數應用不會受到影響。但是,如果您需要使用電話身份驗證登錄大量用戶,則可能需要升級您的定價計劃。請參閱定價頁面。
設置 reCAPTCHA 驗證程序
在使用電話號碼登錄用戶之前,您必須設置 Firebase 的 reCAPTCHA 驗證器。 Firebase 使用 reCAPTCHA 來防止濫用,例如通過確保電話號碼驗證請求來自您應用的允許域之一。
您無需手動設置 reCAPTCHA 客戶端;當您使用 Firebase SDK 的RecaptchaVerifier
對象時,Firebase 會自動創建並處理任何必要的客戶端密鑰和機密。
RecaptchaVerifier
對象支持不可見的 reCAPTCHA ,它通常可以在不需要任何用戶操作的情況下驗證用戶,以及 reCAPTCHA 小部件,它始終需要用戶交互才能成功完成。
通過在呈現 reCAPTCHA 之前更新 Auth 實例上的語言代碼,可以將底層呈現的 reCAPTCHA 本地化為用戶的偏好。上述本地化也適用於發送給用戶的包含驗證碼的 SMS 消息。
Web modular API
import { getAuth } from "firebase/auth"; const auth = getAuth(); auth.languageCode = 'it'; // To apply the default browser preference instead of explicitly setting it. // auth.useDeviceLanguage();
Web namespaced API
firebase.auth().languageCode = 'it'; // To apply the default browser preference instead of explicitly setting it. // firebase.auth().useDeviceLanguage();
使用不可見的 reCAPTCHA
要使用不可見的 reCAPTCHA,請創建一個RecaptchaVerifier
對象,並將size
參數設置為invisible
,指定提交登錄表單的按鈕的 ID。例如:
Web modular API
import { getAuth, RecaptchaVerifier } from "firebase/auth"; const auth = getAuth(); window.recaptchaVerifier = new RecaptchaVerifier(auth, 'sign-in-button', { 'size': 'invisible', 'callback': (response) => { // reCAPTCHA solved, allow signInWithPhoneNumber. onSignInSubmit(); } });
Web namespaced API
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', { 'size': 'invisible', 'callback': (response) => { // reCAPTCHA solved, allow signInWithPhoneNumber. onSignInSubmit(); } });
使用 reCAPTCHA 小部件
要使用可見的 reCAPTCHA 小部件,請在您的頁面上創建一個元素以包含該小部件,然後創建一個RecaptchaVerifier
對象,並在創建時指定容器的 ID。例如:
Web modular API
import { getAuth, RecaptchaVerifier } from "firebase/auth"; const auth = getAuth(); window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {});
Web namespaced API
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
可選:指定 reCAPTCHA 參數
您可以選擇在RecaptchaVerifier
對像上設置回調函數,當用戶解決 reCAPTCHA 或 reCAPTCHA 在用戶提交表單之前過期時調用:
Web modular API
import { getAuth, RecaptchaVerifier } from "firebase/auth"; const auth = getAuth(); window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', { 'size': 'normal', 'callback': (response) => { // reCAPTCHA solved, allow signInWithPhoneNumber. // ... }, 'expired-callback': () => { // Response expired. Ask user to solve reCAPTCHA again. // ... } });
Web namespaced API
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
如果您想在提交登錄請求之前預呈現 reCAPTCHA,請調用render
:
Web modular API
recaptchaVerifier.render().then((widgetId) => { window.recaptchaWidgetId = widgetId; });
Web namespaced API
recaptchaVerifier.render().then((widgetId) => { window.recaptchaWidgetId = widgetId; });
render
解析後,您將獲得 reCAPTCHA 的小部件 ID,您可以使用它來調用reCAPTCHA API:
Web modular API
const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);
Web namespaced API
const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);
發送驗證碼到用戶手機
要啟動電話號碼登錄,請向用戶顯示一個提示他們提供電話號碼的界面,然後調用signInWithPhoneNumber
以請求 Firebase 通過短信向用戶的電話發送驗證碼:
獲取用戶的電話號碼。
法律要求各不相同,但作為最佳實踐並為您的用戶設定期望,您應該告知他們,如果他們使用手機登錄,他們可能會收到一條短信進行驗證,並適用標準費率。
- 調用
signInWithPhoneNumber
,將用戶的電話號碼和您之前創建的RecaptchaVerifier
傳遞給它。如果Web modular API
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 // ... });
Web namespaced API
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
導致錯誤,請重置 reCAPTCHA,以便用戶可以重試:grecaptcha.reset(window.recaptchaWidgetId); // Or, if you haven't stored the widget ID: window.recaptchaVerifier.render().then(function(widgetId) { grecaptcha.reset(widgetId); });
signInWithPhoneNumber
方法向用戶發出 reCAPTCHA 質詢,如果用戶通過質詢,則請求 Firebase 身份驗證向用戶手機發送包含驗證碼的短信。
使用驗證碼登錄用戶
調用signInWithPhoneNumber
成功後,提示用戶輸入短信收到的驗證碼。然後,通過將代碼傳遞給傳遞給signInWithPhoneNumber
的執行處理程序(即,其then
塊)的ConfirmationResult
對象的confirm
方法來讓用戶登錄。例如:
Web modular API
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?) // ... });
Web namespaced API
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 消息的情況下測試電話號碼身份驗證。
- 使用相同的電話號碼運行連續測試而不會受到限制。如果審閱者碰巧使用相同的電話號碼進行測試,這可以最大限度地降低應用商店審閱過程中被拒絕的風險。
- 無需任何額外工作即可在開發環境中輕鬆進行測試,例如無需 Google Play 服務即可在 iOS 模擬器或 Android 模擬器中進行開發的能力。
- 編寫集成測試,而不會被通常應用於生產環境中真實電話號碼的安全檢查所阻止。
虛構的電話號碼必須滿足以下要求:
- 確保您使用的電話號碼確實是虛構的,並且不存在。 Firebase 身份驗證不允許您將真實用戶使用的現有電話號碼設置為測試號碼。一種選擇是使用 555 前綴號碼作為美國測試電話號碼,例如: +1 650-555-3434
- 電話號碼必鬚根據長度和其他限制正確格式化。他們仍將通過與真實用戶電話號碼相同的驗證。
- 您最多可以添加 10 個電話號碼進行開發。
- 使用難以猜測並經常更改的測試電話號碼/代碼。
創建虛構的電話號碼和驗證碼
- 在Firebase 控制台中,打開身份驗證部分。
- 在“登錄方法”選項卡中,啟用電話提供商(如果尚未啟用)。
- 打開用於測試手風琴菜單的電話號碼。
- 提供您要測試的電話號碼,例如: +1 650-555-3434 。
- 提供該特定號碼的 6 位驗證碼,例如: 654321 。
- 添加號碼。如果需要,您可以通過將鼠標懸停在相應行上並單擊垃圾桶圖標來刪除電話號碼及其代碼。
手動測試
您可以直接開始在您的應用程序中使用虛構的電話號碼。這使您可以在開發階段執行手動測試,而不會遇到配額問題或限制。您還可以在未安裝 Google Play 服務的情況下直接從 iOS 模擬器或 Android 模擬器進行測試。
當您提供虛構的電話號碼並發送驗證碼時,不會發送實際的短信。相反,您需要提供之前配置的驗證碼才能完成登錄。
登錄完成後,將使用該電話號碼創建一個 Firebase 用戶。用戶與真實電話號碼用戶具有相同的行為和屬性,可以通過相同的方式訪問實時數據庫/Cloud Firestore 等服務。在此過程中生成的 ID 令牌與真實電話號碼用戶具有相同的簽名。
如果您想進一步限制訪問,另一種選擇是通過對這些用戶的自定義聲明設置測試角色,以將他們區分為假用戶。
集成測試
除了手動測試之外,Firebase 身份驗證還提供 API 來幫助編寫電話身份驗證測試的集成測試。這些 API 通過禁用 Web 中的 reCAPTCHA 要求和 iOS 中的靜默推送通知來禁用應用程序驗證。這使得在這些流程中進行自動化測試成為可能,並且更容易實施。此外,它們還有助於提供在 Android 上測試即時驗證流程的能力。
在 Web 上,在呈現firebase.auth.RecaptchaVerifier
之前將appVerificationDisabledForTesting
設置為true
。這會自動解析 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 應用程序驗證器的行為不同:
- Visible reCAPTCHA :當通過
appVerifier.render()
呈現可見 reCAPTCHA 時,它會在幾分之一秒延遲後自動解析。這相當於用戶在呈現後立即單擊 reCAPTCHA。 reCAPTCHA 響應將在一段時間後過期,然後再次自動解析。 - 不可見的 reCAPTCHA :不可見的 reCAPTCHA 不會在呈現時自動解析,而是在
appVerifier.verify()
調用時或在延遲幾分之一秒後單擊 reCAPTCHA 的按鈕錨點時自動解析。同樣,響應將在一段時間後過期,並且只會在appVerifier.verify()
調用後或再次單擊 reCAPTCHA 的按鈕錨點時自動解析。
每當模擬 reCAPTCHA 被解析時,相應的回調函數就會像預期的那樣被假響應觸發。如果還指定了過期回調,它將在過期時觸發。
下一步
用戶首次登錄後,將創建一個新的用戶帳戶並將其鏈接到用戶登錄所用的憑據,即用戶名和密碼、電話號碼或身份驗證提供商信息。這個新帳戶存儲為您的 Firebase 項目的一部分,可用於在項目中的每個應用程序中識別用戶,無論用戶如何登錄。
在您的應用程序中,了解用戶身份驗證狀態的推薦方法是在
Auth
對像上設置觀察者。然後,您可以從User
對像中獲取用戶的基本個人資料信息。請參閱管理用戶。在您的 Firebase Realtime Database 和 Cloud Storage Security Rules中,您可以從
auth
變量中獲取登錄用戶的唯一用戶 ID,並使用它來控制用戶可以訪問哪些數據。
您可以允許用戶使用多個身份驗證提供程序登錄您的應用程序,方法是將身份驗證提供程序憑據鏈接到現有用戶帳戶。
要註銷用戶,請調用signOut
:
Web modular API
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut(auth).then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });
Web namespaced API
firebase.auth().signOut().then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });