如果您已升級至提供 Identity Platform 的 Firebase 驗證,就可以在 Flutter 應用程式中新增簡訊多重驗證機制。
多重驗證 (MFA) 可提升應用程式的安全性。雖然攻擊者通常會竊取密碼及盜用社群媒體帳戶,但攔截簡訊的難度較高。
事前準備
至少啟用一個支援多重驗證的供應商。除了電話驗證、匿名驗證和 Apple Game Center 以外,所有供應商都支援 MFA。
請確認您的應用程式會驗證使用者的電子郵件地址。多重驗證需要通過電子郵件驗證。這麼做可防止惡意人士使用不屬於自己的電子郵件地址註冊服務,然後透過新增第二個因素將真正的擁有者鎖在門外。
Android:如果您尚未在 Firebase 控制台中設定應用程式的 SHA-256 雜湊,請進行設定。如要瞭解如何找出應用程式的 SHA-256 雜湊,請參閱「驗證用戶端」一文。
iOS:在 Xcode 中為專案啟用推播通知,並確認 APN 驗證金鑰已透過 Firebase 雲端通訊 (FCM) 設定。此外,您必須啟用背景模式,才能傳送遠端通知。如需這項步驟的詳細說明,請參閱 Firebase iOS 電話驗證說明文件。
網頁:請確認您已在 Firebase 主控台的 OAuth 重新導向網域下方新增應用程式網域。
啟用多重驗證
開啟 Firebase 控制台的「Authentication > Sign-in method」頁面。
在「進階」部分中,啟用「簡訊多重驗證」。
您也應輸入要用來測試應用程式的電話號碼。雖然這不是必要步驟,我們仍強烈建議您註冊測試電話號碼,以免在開發期間發生節流情形。
如果您尚未授權應用程式的網域,請前往 Firebase 控制台的「Authentication > Settings」頁面,將該網域新增至許可清單。
選擇註冊模式
您可以選擇應用程式是否需要多重驗證,以及註冊使用者的方式和時間。常見的模式包括:
在註冊過程中註冊使用者的第二重驗證。如果您的應用程式要求所有使用者都必須進行多重驗證,請使用這個方法。
提供可略過的選項,讓使用者在註冊時註冊第二重驗證。如要鼓勵使用者採用多重驗證,但不強制要求使用者採用,則可能會偏好這種做法。
提供從使用者帳戶或個人資料管理頁面新增第二因素的功能,而非在註冊畫面中提供。這樣一來,註冊程序的摩擦力會降到最低,同時仍可讓重視安全性的使用者使用多重驗證。
當使用者想要存取需要更高安全性要求的功能時,要求逐步新增第二個因素。
註冊次要驗證方式
如要為使用者註冊新的次要驗證方法,請按照下列步驟操作:
重新驗證使用者。
請使用者輸入電話號碼。
為使用者取得多重驗證工作階段:
final multiFactorSession = await user.multiFactor.getSession();
使用多重驗證會話和回撥電話驗證電話號碼:
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: multiFactorSession, phoneNumber: phoneNumber, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // The SMS verification code has been sent to the provided phone number. // ... }, codeAutoRetrievalTimeout: (_) {}, );
傳送簡訊碼後,請要求使用者驗證這組碼:
final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, );
完成註冊程序:
await user.multiFactor.enroll( PhoneMultiFactorGenerator.getAssertion( credential, ), );
以下程式碼為註冊第二個因素的完整範例:
final session = await user.multiFactor.getSession();
final auth = FirebaseAuth.instance;
await auth.verifyPhoneNumber(
multiFactorSession: session,
phoneNumber: phoneController.text,
verificationCompleted: (_) {},
verificationFailed: (_) {},
codeSent: (String verificationId, int? resendToken) async {
// See `firebase_auth` example app for a method of retrieving user's sms code:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
final smsCode = await getSmsCodeFromUser(context);
if (smsCode != null) {
// Create a PhoneAuthCredential with the code
final credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsCode,
);
try {
await user.multiFactor.enroll(
PhoneMultiFactorGenerator.getAssertion(
credential,
),
);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
},
codeAutoRetrievalTimeout: (_) {},
);
恭喜!您已為使用者成功註冊第二個驗證因素。
使用第二種驗證方法登入
如要使用簡訊雙重驗證登入使用者,請按照下列步驟操作:
請使用者以第一個因素登入,然後擷取
FirebaseAuthMultiFactorException
例外狀況。這個錯誤包含解析器,可用於取得使用者註冊的第二因素。它還包含一個基礎工作階段,證明使用者已成功透過第一因素驗證。舉例來說,如果使用者的第一個因素是電子郵件和密碼:
try { await _auth.signInWithEmailAndPassword( email: emailController.text, password: passwordController.text, ); // User is not enrolled with a second factor and is successfully // signed in. // ... } on FirebaseAuthMultiFactorException catch (e) { // The user is a multi-factor user. Second factor challenge is required final resolver = e.resolver // ... }
如果使用者註冊了多個次要驗證因素,請詢問他們要使用哪一個:
final session = e.resolver.session; final hint = e.resolver.hints[selectedHint];
傳送驗證訊息給使用者的手機,並附上提示和多重驗證會話:
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: session, multiFactorInfo: hint, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // ... }, codeAutoRetrievalTimeout: (_) {}, );
請呼叫
resolver.resolveSignIn()
完成次要驗證:final smsCode = await getSmsCodeFromUser(context); if (smsCode != null) { // Create a PhoneAuthCredential with the code final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, ); try { await e.resolver.resolveSignIn( PhoneMultiFactorGenerator.getAssertion(credential) ); } on FirebaseAuthException catch (e) { print(e.message); } }
以下程式碼為多重驗證使用者登入的完整範例:
try {
await _auth.signInWithEmailAndPassword(
email: emailController.text,
password: passwordController.text,
);
} on FirebaseAuthMultiFactorException catch (e) {
setState(() {
error = '${e.message}';
});
final firstHint = e.resolver.hints.first;
if (firstHint is! PhoneMultiFactorInfo) {
return;
}
await FirebaseAuth.instance.verifyPhoneNumber(
multiFactorSession: e.resolver.session,
multiFactorInfo: firstHint,
verificationCompleted: (_) {},
verificationFailed: (_) {},
codeSent: (String verificationId, int? resendToken) async {
// See `firebase_auth` example app for a method of retrieving user's sms code:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
final smsCode = await getSmsCodeFromUser(context);
if (smsCode != null) {
// Create a PhoneAuthCredential with the code
final credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsCode,
);
try {
await e.resolver.resolveSignIn(
PhoneMultiFactorGenerator.getAssertion(
credential,
),
);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
},
codeAutoRetrievalTimeout: (_) {},
);
} catch (e) {
...
}
恭喜!您已成功使用多重驗證登入使用者。
後續步驟
- 使用 Admin SDK 以程式輔助的方式管理多重驗證使用者。