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}'); } }
- 該功能需要更新為非同步,因為我們將在註冊期間使用 await。
- 在註冊過程中,我們必須建立 userAttributes 以傳入使用者的電子郵箱。
- 我們將傳遞登入資料提供的使用者名稱和密碼,以及包含要使用 Cognito 註冊之電子郵箱的使用者屬性。由於這是非同步程序,因此必須使用 await 關鍵字。
- 如果我們成功返回結果,下一步應是驗證其電子郵箱。如果出於任何原因完成註冊程序,我們只需將使用者登入該應用程式。
- 當使用者驗證其電子郵箱時,我們會將 SignUpCredentials 存放在 _credentials 中。
- 與之前一樣,我們將 AuthState 更新為驗證狀態,但僅在成功登入並確定註冊程序未完成之後,才會進行身份驗證。
- 如果出於任何原因註冊失敗,我們只需將錯誤輸出至日誌。
將 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}'); } }
- 正如我們對 signUpWithCredentials 執行的操作,verifyCode 也需要標記為非同步函數。
- 我們將使用 _credentials 提供使用者名稱,並將輸入的程式碼從 VerificationPage 傳遞至 ConfirmSignUp。
- 如果來自 ConfirmSignUp 的結果表明註冊已完成,我們則會嘗試使用在註冊期間建立的 _credentials 登入使用者。務必注意,在成功案例中,我們不再更新 AppState,因為使用者仍需登入 Amplify。
- 如果註冊未完成,則使用結果來尋找需要採取哪些進一步的步驟來完成註冊。這不應在我們的應用程式中發生。
我們已實作身份驗證流程的註冊部分,但現在我們需要更新登入部分。將 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}'); } }
- 由於 loginWithCredentials 將 AuthCredentials 作為參數,因此無論傳遞 LoginCredentials 還是 SignUpCredentials,都將發揮作用。
- 我們正在將 AuthCredentials 使用者名稱和密碼傳遞至 Amplify 登入方法,並等待結果。
- 如果登入成功,並且結果上的 isSignedIn 屬性確認使用者現已登入,我們會將狀態更新為工作階段。
- 在我們的應用程式中不應出於此狀態。如果使用者輸入錯誤的登入資料或遇到任何其他錯誤,則會產生我們的擷取區塊。
現在,更新 logOut 方法:
void logOut() async { try { // 1 await Amplify.Auth.signOut(); // 2 showLogin(); } on AuthError catch (authError) { print('Could not log out - ${authError.cause}'); } }
- 若我們在不傳遞任何選項的情況下叫用 Auth.signOut(),則僅在此裝置上登出使用者,而非在所有裝置上登出該使用者。
- 我們可以重新使用 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 }
這些是補充我們現有身份驗證流程所需的唯一修改。建置並執行該應用程式,您應能夠註冊,確認電子郵箱,登出,然後再次登入。