電話驗證功能可讓使用者使用手機做為驗證器登入 Firebase。系統會透過簡訊將含有專屬代碼的簡訊傳送給使用者 (使用所提供的電話號碼)。使用者取得程式碼授權後,就能登入 Firebase。
Google 會傳送並儲存使用者用於驗證的電話號碼,以改善 Google 服務 (包含但不限於 Firebase) 的垃圾內容和濫用行為防範情形。使用 Firebase 驗證電話號碼登入服務前,開發人員應先確保已取得適當的使用者同意聲明。
Firebase 電話驗證功能僅適用於部分國家/地區。詳情請參閱對方的常見問題。
設定
在開始使用電話驗證之前,請確定你已按照下列步驟操作:
- 在 Firebase 控制台啟用「電話」做為登入方式。
- Android:如果您尚未在 Firebase 主控台設定應用程式的 SHA-1 雜湊,請按照這些步驟操作。 如要瞭解如何找出應用程式的 SHA-1 雜湊,請參閱「驗證用戶端」。
- iOS:在 Xcode 中,為專案啟用推播通知,並確定您的 APN 驗證金鑰已透過 Firebase 雲端通訊 (FCM) 進行設定。此外,您也必須為遠端通知啟用背景模式。如要深入瞭解這個步驟,請參閱 Firebase iOS 手機驗證說明文件。
- 網路:確認您已在 Firebase 主控台的「OAuth 重新導向網域」下方新增應用程式網域。
注意:電話號碼登入功能只能在實體裝置和網路上使用。如要在裝置模擬器中測試驗證流程,請參閱測試。
用量
Firebase Authentication SDK for Flutter 提供兩種使用者透過電話號碼登入的方式。原生 (例如 Android 和 iOS) 平台用來驗證電話號碼的功能與網頁提供的不同,因此每種平台都提供兩種專屬方法:
- 原生平台:
verifyPhoneNumber
。 - Web Platform:
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:處理自動簡訊代碼處理失敗時的逾時情況。
驗證完成
只有在支援自動簡訊代碼解析的 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);
},
);
驗證失敗
如果 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
},
);
驗證碼傳送
當 Firebase 傳送簡訊代碼至裝置時,系統會以 verificationId
和 resendToken
觸發這個處理常式 (resendToken
僅適用於 Android 裝置,iOS 裝置「一律」會傳回 null
值)。
觸發後,建議您更新應用程式使用者介面,提示使用者輸入預期的簡訊代碼。輸入簡訊驗證碼後,您可以將驗證 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 小工具,以證明自己為真人。確認後,系統會傳送 SMS 代碼。
根據預設,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
確認結果處理常式。