在 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) {
 
...
}

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

後續步驟