在 Flutter 應用程式中新增多重驗證機制

如果您已透過 Identity Platform 升級至 Firebase 驗證, 您可以在 Flutter 應用程式中新增簡訊多重驗證。

多重驗證 (MFA) 可提升應用程式的安全性。雖然攻擊者 經常會竊取密碼和社群媒體帳戶、攔截簡訊, 變得更困難

事前準備

  1. 請至少啟用一個支援多重驗證的供應商。 每個供應商都支援多重驗證,但電話驗證、匿名驗證和 Apple Game Center。

  2. 確認應用程式正在驗證使用者的電子郵件地址。MFA 需要電子郵件驗證。 這可防止惡意人士利用電子郵件註冊服務 成為非擁有人,進而鎖定真正的擁有者 。

  3. Android:如果您尚未在 Firebase 控制台可完成這項操作。 請參閱驗證用戶端 瞭解如何找出應用程式的 SHA-256 雜湊。

  4. iOS:在 Xcode 中,為專案啟用推播通知,並確保 您的 APN 驗證金鑰已透過 Firebase 雲端通訊 (FCM) 進行設定。此外,您也必須遵守 啟用遠端通知的背景模式。 如要深入瞭解這個步驟,請參閱 Firebase iOS 手機驗證說明文件。

  5. 網路:請確認您已在 Firebase 主控台OAuth 重新導向網域

啟用多重驗證

  1. 開啟「驗證 >登入方式 頁面。

  2. 在「進階」部分中,啟用「簡訊多重驗證」

    請一併輸入要測試應用程式的電話號碼。 雖然非必要,但我們強烈建議您註冊測試電話號碼 避免開發過程中發生節流現象

  3. 如果您尚未授權應用程式的網域,請將網域新增至允許清單 [驗證] > 中的清單設定 頁面。

選擇註冊模式

您可以選擇是否要讓應用程式需要多因素驗證,以及如何 以及註冊使用者的時間常見的模式包括:

  • 註冊使用者的第二重驗證在註冊過程中。使用這份草稿 方法。

  • 提供可略過的選項,讓使用者在註冊期間註冊第二個步驟。應用程式 希望 (但不需要) 多因素驗證 他們偏好使用這個方法。

  • 讓使用者能夠在帳戶或設定檔中新增次要驗證條件 而非註冊畫面這可以大幅減少 同時在進行多因素驗證時 。

  • 使用者要存取應用程式時,需要逐步新增第二個驗證步驟 強化安全性要求的功能

註冊次要驗證方式

如何為使用者註冊新的次要驗證條件:

  1. 重新驗證使用者。

  2. 請使用者輸入電話號碼。

  3. 為使用者取得多重要素工作階段:

    final multiFactorSession = await user.multiFactor.getSession();
    
  4. 請使用多重要素工作階段和回呼驗證電話號碼:

    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: (_) {},
    ); 
    
  5. 讓系統傳送簡訊驗證碼後,要求使用者驗證驗證碼:

    final credential = PhoneAuthProvider.credential(
      verificationId: verificationId,
      smsCode: smsCode,
    );
    
  6. 完成註冊:

    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/master/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: (_) {},
  );

恭喜!您已成功註冊以下項目的第二個驗證方式: 而非個別使用者的帳戶

透過次要驗證方式登入使用者

如何透過雙重簡訊驗證功能登入使用者帳戶:

  1. 透過第一個步驟登入使用者,然後擷取 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
      // ...
    }
    
  2. 如果使用者已註冊多項次要驗證因素,請詢問他們哪個 使用:

    final session = e.resolver.session;
    
    final hint = e.resolver.hints[selectedHint];
    
  3. 傳送驗證訊息到使用者的手機,同時提示提示和 多因素工作階段:

    await FirebaseAuth.instance.verifyPhoneNumber(
      multiFactorSession: session,
      multiFactorInfo: hint,
      verificationCompleted: (_) {},
      verificationFailed: (_) {},
      codeSent: (String verificationId, int? resendToken) async {
        // ...
      },
      codeAutoRetrievalTimeout: (_) {},
    );
    
  4. 呼叫 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/master/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) {
  ...
} 

恭喜!您已成功透過多重要素登入使用者 驗證。

後續步驟