AWS 入門

建置 Flutter 應用程式

使用 AWS Amplify 建立簡單的 Flutter 應用程式

第三單元:新增身份驗證

在本單元中,您將使用 Amplify CLI 和程式庫來設定應用程式,並新增身份驗證。

簡介

您將新增至應用程式的第一個 Amplify 類別將是身份驗證。Amplify 在後台利用 Amazon Cognito 來管理使用者集區和身份集區。

在本單元中,您將了解如何註冊、確認、登入和登出使用者。我們只需使用幾行程式碼即可實作每個螢幕的功能。

您將學到的內容

  • 設定身份驗證類別
  • 註冊使用者
  • 驗證使用者電子郵件
  • 登入經過身份驗證的使用者
  • 登出經過身份驗證的使用者

主要概念

身份驗證 – 身份驗證是指驗證和管理使用者的程序,以允許其與應用程式的資源進行互動。

 完成時間

10 分鐘

 使用的服務

實作

  • 建立身份驗證服務

    若要將身份驗證服務新增至我們的 Amplify 專案,我們需要在專案根目錄下的終端機中執行以下命令

    amplify add auth

    系統會提示您一些有關身份驗證服務組態的問題。按 Enter 鍵為每個問題選擇預設值。產生的輸出應如下所示:

    ➜  photo_gallery git:(master) ✗ amplify add auth
    Using service: Cognito, provided by: awscloudformation
    
     The current configured provider is Amazon Cognito.
    
     Do you want to use the default authentication and security configuration? Default configuration
     Warning: you will not be able to edit these selections.
     How do you want users to be able to sign in? Username
     Do you want to configure advanced settings? No, I am done.

    完全身份驗證資源後,您應取得如下輸出:

    Successfully added resource photogallery42b5391b locally

    如上面的輸出所示,該資源僅在本機新增。為了使用我們在本機做出的變更來設定後端,必須執行以下命令:

    amplify push

    在將本機變更傳送至後端之前,Amplify CLI 將顯示狀態報告,以確保您要推送以下變更:

    Current Environment: dev
    
    | Category | Resource name        | Operation | Provider plugin   |
    | -------- | -------------------- | --------- | ----------------- |
    | Auth     | photogallery42b5391b | Create    | awscloudformation |
    ? Are you sure you want to continue? Yes

    在將本機變更傳送至後端之前,Amplify CLI 將顯示狀態報告,以確保您要推送以下變更:

    ✔ All resources are updated in the cloud

    您還可以透過檢視 /lib/amplifyconfiguration.dart 檔案並檢查身份驗證值,來確認身份驗證資源是否已正確設定。

  • 安裝相依項

    返回 Visual Studio Code,開啟 pubspec.yaml 並新增以下相依項:

    ... # amplify_core: '<1.0.0'
    
    amplify_auth_cognito: '<1.0.0'
    
    ... # dev_dependencies:

    現在儲存檔案,以使 Visual Studio Code 安裝 Amplify Auth Cognito 外掛程式。如果未在儲存時安裝相依項,還可以從終端機執行 $ flutter pub get。

    您應取得以下輸出:

    exit code 0
  • 設定外掛程式

    現在已安裝身份驗證相依項,我們可以將身份驗證外掛程式新增至 main.dart 檔案的 _MyAppState._configureAmplify() 中的 Amplify 執行個體:

    ... // void _configureAmplify() async {
    
    _amplify.addPlugin(authPlugins: [AmplifyAuthCognito()]);
    
    ... // try {

    現在執行該應用程式,並確認您仍在日誌中收到成功訊息。

    如果繼續收到成功訊息,則現在可以開始實作身份驗證流程的功能。如果不是,請重複上述步驟或瀏覽初始化 Amplify 單元,並確保已按照此處的所有步驟進行操作。

  • 實作功能

    返回建立 Flutter 應用程式單元,我們已實作 AuthService 來根據叫用的函數處理 AuthState 的更新。現在,我們需要更新每個功能,以僅在使用者成功完成每項程序時才更新狀態。

    在 AuthService 的 auth_service.dart 中新增 AuthCredentials 屬性:

    ... // final authStateController = StreamController<AuthState>();
    
    AuthCredentials _credentials;
    
    ... // void showSignUp() {

    該屬性將用於註冊期間將 SignUpCredentials 保留在記憶體中,以便使用者在驗證其電子郵件地址後可以立即登入。如果我們不這樣做,使用者需要前往登入螢幕來手動登入。

    將 signUpWithCredentials 更新為以下內容:

    // 1
    void signUpWithCredentials(SignUpCredentials credentials) async {
      try {
        // 2
        final userAttributes = {'email': credentials.email};
    
        // 3
        final result = await Amplify.Auth.signUp(
            username: credentials.username,
            password: credentials.password,
            options: CognitoSignUpOptions(userAttributes: userAttributes));
    
        // 4
        if (result.isSignUpComplete) {
          loginWithCredentials(credentials);
        } else {
          // 5
          this._credentials = credentials;
    
          // 6
          final state = AuthState(authFlowStatus: AuthFlowStatus.verification);
          authStateController.add(state);
        }
      
      // 7
      } on AuthError catch (authError) {
        print('Failed to sign up - ${authError.cause}');
      }
    }
    1. 該功能需要更新為非同步,因為我們將在註冊期間使用 await。
    2. 在註冊過程中,我們必須建立 userAttributes 以傳入使用者的電子郵箱。
    3. 我們將傳遞登入資料提供的使用者名稱和密碼,以及包含要使用 Cognito 註冊之電子郵箱的使用者屬性。由於這是非同步程序,因此必須使用 await 關鍵字。
    4. 如果我們成功返回結果,下一步應是驗證其電子郵箱。如果出於任何原因完成註冊程序,我們只需將使用者登入該應用程式。
    5. 當使用者驗證其電子郵箱時,我們會將 SignUpCredentials 存放在 _credentials 中。
    6. 與之前一樣,我們將 AuthState 更新為驗證狀態,但僅在成功登入並確定註冊程序未完成之後,才會進行身份驗證。
    7. 如果出於任何原因註冊失敗,我們只需將錯誤輸出至日誌。

    將 verifyCode 更新為:

    // 1
    void verifyCode(String verificationCode) async {
     try {
       // 2
       final result = await Amplify.Auth.confirmSignUp(
           username: _credentials.username, confirmationCode: verificationCode);
    
       // 3
       if (result.isSignUpComplete) {
         loginWithCredentials(_credentials);
       } else {
         // 4
         // Follow more steps
       }
     } on AuthError catch (authError) {
       print('Could not verify code - ${authError.cause}');
     }
    }
    1. 正如我們對 signUpWithCredentials 執行的操作,verifyCode 也需要標記為非同步函數。
    2. 我們將使用 _credentials 提供使用者名稱,並將輸入的程式碼從 VerificationPage 傳遞至 ConfirmSignUp。
    3. 如果來自 ConfirmSignUp 的結果表明註冊已完成,我們則會嘗試使用在註冊期間建立的 _credentials 登入使用者。務必注意,在成功案例中,我們不再更新 AppState,因為使用者仍需登入 Amplify。
    4. 如果註冊未完成,則使用結果來尋找需要採取哪些進一步的步驟來完成註冊。這不應在我們的應用程式中發生。

    我們已實作身份驗證流程的註冊部分,但現在我們需要更新登入部分。將 loginWithCredentials 更新為以下內容:

    // 1
    void loginWithCredentials(AuthCredentials credentials) async {
     try {
       // 2
       final result = await Amplify.Auth.signIn(
           username: credentials.username, password: credentials.password);
    
       // 3
       if (result.isSignedIn) {
         final state = AuthState(authFlowStatus: AuthFlowStatus.session);
         authStateController.add(state);
       } else {
         // 4
         print('User could not be signed in');
       }
     } on AuthError catch (authError) {
       print('Could not login - ${authError.cause}');
     }
    }
    1. 由於 loginWithCredentials 將 AuthCredentials 作為參數,因此無論傳遞 LoginCredentials 還是 SignUpCredentials,都將發揮作用。
    2. 我們正在將 AuthCredentials 使用者名稱和密碼傳遞至 Amplify 登入方法,並等待結果。
    3. 如果登入成功,並且結果上的 isSignedIn 屬性確認使用者現已登入,我們會將狀態更新為工作階段。
    4. 在我們的應用程式中不應出於此狀態。如果使用者輸入錯誤的登入資料或遇到任何其他錯誤,則會產生我們的擷取區塊。

    現在,更新 logOut 方法:

    void logOut() async {
     try {
       // 1
       await Amplify.Auth.signOut();
    
       // 2
       showLogin();
     } on AuthError catch (authError) {
       print('Could not log out - ${authError.cause}');
     }
    }
    1. 若我們在不傳遞任何選項的情況下叫用 Auth.signOut(),則僅在此裝置上登出使用者,而非在所有裝置上登出該使用者。
    2. 我們可以重新使用 showLogin() 方法來更新狀態,並在登出成功後將使用者返回登入螢幕。

    最後,如果使用者關閉該應用程式但在上一個工作階段期間已登入,則我們需要能夠自動登入該使用者。將此最終功能新增至 AuthService。

    void checkAuthStatus() async {
     try {
       await Amplify.Auth.fetchAuthSession();
    
       final state = AuthState(authFlowStatus: AuthFlowStatus.session);
       authStateController.add(state);
     } catch (_) {
       final state = AuthState(authFlowStatus: AuthFlowStatus.login);
       authStateController.add(state);
     }
    }

    checkAuthStatus 將嘗試取得目前的 AuthSession;如果成功,則使用者將登入。如果擷取失敗,則意味著該使用者尚未登入,應顯示 LoginPage。

    目前,我們正在 _MyAppState 的 initState 方法內部叫用 showLogin。我們來將其變更為 checkAuthStatus:

    ... // _configureAmplify();
    
    _authService.checkAuthStatus();
    
    ... // initState closing }

    這些是補充我們現有身份驗證流程所需的唯一修改。建置並執行該應用程式,您應能夠註冊,確認電子郵箱,登出,然後再次登入。

    EndofModule3-gif

結論

您已成功將使用者身份驗證新增至 Photo Gallery 應用程式! 在下一個單元中,您將學習如何為應用程式新增儲存體。

這個單元對您是否有幫助?

感謝您
請告訴我們您喜歡的部分。
關閉
抱歉,讓您失望
是有內容過時、令人困擾,或不準確嗎? 請提供意見回饋,協助我們改進此教學課程。
關閉

新增儲存體