電話驗證功能可讓使用者使用手機做為驗證工具登入 Firebase。系統會傳送簡訊給使用者 (使用提供的電話號碼),內含專屬驗證碼。授權碼經過授權後,使用者就能登入 Firebase。
使用者提供的電話號碼會傳送至 Google 並儲存,以便 Google 服務 (包括但不限於 Firebase) 防範垃圾內容和濫用行為。開發人員應先取得適當的使用者同意聲明,再使用 Firebase 驗證服務的電話號碼登入服務。
Firebase 電話驗證功能並未在所有國家/地區推出。詳情請參閱常見問題。
設定
開始使用電話驗證功能前,請確認您已完成下列步驟:
- 在 Firebase 主控台中啟用電話號碼做為登入方式。
- Android:如果您尚未在 Firebase 控制台中設定應用程式的 SHA-1 雜湊,請進行設定。如要瞭解如何尋找應用程式的 SHA-1 雜湊,請參閱「驗證用戶端」一文。
- iOS:在 Xcode 中為專案啟用推播通知,並確認 APN 驗證金鑰已透過 Firebase 雲端通訊 (FCM) 設定。此外,您必須啟用背景模式,才能傳送遠端通知。如需這項步驟的詳細說明,請參閱 Firebase iOS 電話驗證說明文件。
- 網頁:請確認您已在 Firebase 主控台的 OAuth 重新導向網域下方新增應用程式網域。
注意:電話號碼登入功能僅適用於實際裝置和網頁。如要在裝置模擬器上測試驗證流程,請參閱「測試」一文。
用量
Flutter 專用的 Firebase 驗證 SDK 提供兩種方式,讓使用者可透過電話號碼登入。原生 (例如 Android 和 iOS) 平台提供的電話號碼驗證功能與網頁不同,因此每個平台都有兩種驗證方法:
- 原生平台:
verifyPhoneNumber
。 - Web 平台:
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 的方式:
- verificationCompleted:在 Android 裝置上自動處理簡訊驗證碼。
- verificationFailed:處理失敗事件,例如無效的電話號碼或是否已超過簡訊配額。
- codeSent:處理 Firebase 已將驗證碼傳送至裝置的情況,用於提示使用者輸入驗證碼。
- codeAutoRetrievalTimeout:處理自動簡訊驗證碼處理作業失敗時的逾時問題。
verificationCompleted
這個處理程序只會在支援自動 SMS 驗證碼解析的 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 傳回錯誤 (例如電話號碼不正確,或專案的 SMS 配額已用盡),系統會將 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 向裝置傳送簡訊驗證碼時,這個處理常式會透過 verificationId
和 resendToken
觸發 (resendToken
僅支援 Android 裝置,iOS 裝置會「一律」傳回 null
值)。
觸發後,您可以更新應用程式 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 近期已傳送簡訊,就不會重新傳送。不過,您可以透過重新呼叫 verifyPhoneNumber
方法,將重傳權杖傳回至 forceResendingToken
引數,藉此覆寫這項行為。如果成功,系統就會重新傳送簡訊。
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 Authentication 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,
));
您可以自訂 size
和 theme
引數,如上方所示,藉此變更大小和主題。
您也可以監聽事件,例如使用者是否已完成 reCAPTCHA、reCAPTCHA 是否已過期或是否已擲回錯誤:
RecaptchaVerifier(
onSuccess: () => print('reCAPTCHA Completed!'),
onError: (FirebaseAuthException error) => print(error),
onExpired: () => print('reCAPTCHA Expired!'),
);
測試
Firebase 支援本機測試電話號碼:
- 在 Firebase 控制台中,選取「電話」驗證方法供應商,然後點選「測試用電話號碼」下拉式選單。
- 輸入新的電話號碼 (例如
+44 7444 555666
) 和測試碼 (例如123456
)。
如果您向 verifyPhoneNumber
或 signInWithPhoneNumber
方法提供測試電話號碼,系統實際上不會傳送簡訊。您可以改為直接將測試代碼提供給 PhoneAuthProvider
,或使用 signInWithPhoneNumber
的確認結果處理常式。