AWS 入門

建置 Android 應用程式

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

單元 3:新增身份驗證

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

簡介

您將新增的下一個功能是使用者身份驗證。在本單元中,您將學習如何利用受管使用者身份供應商 Amazon Cognito 透過 Amplify CLI 和程式庫對使用者進行身份驗證。

您還將學習如何使用 Cognito 託管使用者界面來呈現整個使用者身份驗證流程,僅用幾行程式碼即可允許使用者進行註冊、登入和重置密碼操作。

使用「託管使用者界面」,意味著該應用程式利用 Cognito 網頁進行登入和註冊使用者界面流程。應用程式的使用者將重新定向至 Cognito 託管的網頁,並在登入後重新定向回該應用程式。當然,Cognito 和 Amplify 也支援本機 UI,您可以遵循以下研討會指導,進一步了解有關自訂身份驗證 UI 的資訊。

您將學到的內容

  • 建立和部署身份驗證服務
  • 設定您的 Android 應用程式以包括 Cognito 託管的 UI 身份驗證

主要概念

Amplify 程式庫 – Amplify 程式庫讓您可以透過 Web 或行動應用程式與 AWS 服務進行互動。

身份驗證 – 在軟體中,身份驗證是使用身份驗證服務或 API 驗證和管理使用者身份的過程。

 完成時間

10 分鐘

 使用的服務

實作

  • 若要建立身份驗證服務,請開啟終端機,然後執行以下命令:

    amplify add auth
    
    ? Do you want to use the default authentication and security configuration? Select Default configuration with Social Provider and press enter
    ? How do you want users to be able to sign in? Select the default Username and press enter
    ? Do you want to configure advanced settings? Select the default No, I am done and press enter
    ? What domain name prefix do you want to use? Select the default and press enter
    Enter your redirect signin URI: type gettingstarted:// and press enter
    ? Do you want to add another redirect signin URI? Select the default N and press enter
    Enter your redirect signout URI: type gettingstarted:// and press enter
    ? Do you want to add another redirect signout URI? Select the default N and press enter
    ? Select the social providers you want to configure for your user pool: do not select any provider and press enter

    當您看到此訊息時,則會知道組態已設定成功 (資源的確切名稱會有所差異):

    Successfully added resource androidgettingstartedfc5a4717 locally
  • 現在已經在本機設定了身份驗證服務,我們可以將其部署至雲端。在終端機的專案目錄中執行以下命令

    amplify push
    
    # press Y when asked to continue

    一段時間後,您應看到以下訊息:

    ✔ All resources are updated in the cloud
    
    Hosted UI Endpoint: https://androidgettingstarted-dev.auth.eu-central-1.amazoncognito.com/
    Test Your Hosted UI Endpoint: https://androidgettingstarted-dev.auth.eu-central-1.amazoncognito.com/login?response_type=code&client_id=1234567890&redirect_uri=gettingstarted://
  • 在前往程式碼之前,請返回 Android Studio,然後將以下相依項以及之前新增的其他 `amplifyframework` 實作,新增至單元的 `build.gradle` 中,並在提示時按一下 Sync Now (立即同步):

    dependencies {
        ...
        // Amplify core dependency
        implementation 'com.amplifyframework:core:1.4.0'
        implementation 'com.amplifyframework:aws-auth-cognito:1.4.0'
    }
  • 返回 Android Studio,開啟 Backend.kt 檔案。在後端類別中,向我們在上一部分 (initialize() 方法中) 新增的 Amplify 初始化程式碼新增一行

    完整的程式碼區塊應如下所示:

    // inside Backend class
    fun initialize(applicationContext: Context) : Backend {
        try {
            Amplify.addPlugin(AWSCognitoAuthPlugin())
            Amplify.configure(applicationContext)
    
            Log.i(TAG, "Initialized Amplify")
        } catch (e: AmplifyException) {
            Log.e(TAG, "Could not initialize Amplify", e)
        }
        return this
    }

    請勿忘記新增匯入語句,Android Studio 會自動為您執行該操作 (若是 Mac,在程式碼編輯器偵測到的每個錯誤上按一下 Alt + Enter)。

    如同上一步操作,為每個缺少的類別定義新增所需的匯入語句 (在紅色字詞上按以下 Alt + Enter)。

    若要驗證是否一切如預期,請建置專案。按一下 Build (建置) 功能表,然後選取 Make Project (製作專案),或者在 Mac 上,鍵入 ⌘F9。應不會發生錯誤。

  • 其餘的程式碼變更會追蹤使用者的狀態 (是否已登入?),並在使用者按一下鎖形圖示時,觸發登入/註冊使用者界面。

    a.新增登入和登出方法
    在後端類別中的任意位置,新增以下四種方法:
    private fun updateUserData(withSignedInStatus : Boolean) {
        UserData.setSignedIn(withSignedInStatus)
    }
    
    fun signOut() {
        Log.i(TAG, "Initiate Signout Sequence")
    
        Amplify.Auth.signOut(
            { Log.i(TAG, "Signed out!") },
            { error -> Log.e(TAG, error.toString()) }
        )
    }
    
    fun signIn(callingActivity: Activity) {
        Log.i(TAG, "Initiate Signin Sequence")
    
        Amplify.Auth.signInWithWebUI(
            callingActivity,
            { result: AuthSignInResult ->  Log.i(TAG, result.toString()) },
            { error: AuthException -> Log.e(TAG, error.toString()) }
        )
    }

    然後為每個缺少的類別定義新增所需的匯入語句 (在紅色字詞上按以下 Alt + Enter)。在多個類別之間進行選擇時,請確保從 Amplify 套件中選擇一個,如下面的螢幕擷取畫面所示。

    注意,我們不會從這些方法中更新 UserData.isSignedIn 標誌,這將在下一部分中完成。

    b.新增身份驗證中樞接聽程式

    為了追蹤身份驗證狀態的變化,我們新增了程式碼以訂閱 Amplify 傳送的身份驗證事件。我們使用 Backend.initialize() 方法來初始化中樞。

    收到身份驗證事件後,我們將叫用 updateUserData() 方法。此方法使 UserData 物件保持同步。UserData.isSignedIn 屬性為 LiveData<Boolean>,這意味著當值變更時,將會通知訂閱此屬性的觀察者。我們使用該機制來自動重新整理使用者界面。您可以在 Android 文件中進一步了解有關 LiveData 的資訊

    我們還新增了程式碼,以在應用程式啟動時檢查之前的身份驗證狀態。當應用程式啟動時,其會檢查 Cognito 工作階段是否已存在,並相應地更新 UserData。

    在 Backend.initialize() 中,在試用/擷取區塊之後和返回語句之前新增以下程式碼

    // in Backend.initialize() function, after the try/catch block but before the return statement 
    
    Log.i(TAG, "registering hub event")
    
    // listen to auth event
    Amplify.Hub.subscribe(HubChannel.AUTH) { hubEvent: HubEvent<*> ->
    
        when (hubEvent.name) {
            InitializationStatus.SUCCEEDED.toString() -> {
                Log.i(TAG, "Amplify successfully initialized")
            }
            InitializationStatus.FAILED.toString() -> {
                Log.i(TAG, "Amplify initialization failed")
            }
            else -> {
                when (AuthChannelEventName.valueOf(hubEvent.name)) {
                    AuthChannelEventName.SIGNED_IN -> {
                        updateUserData(true)
                        Log.i(TAG, "HUB : SIGNED_IN")
                    }
                    AuthChannelEventName.SIGNED_OUT -> {
                        updateUserData(false)
                        Log.i(TAG, "HUB : SIGNED_OUT")
                    }
                    else -> Log.i(TAG, """HUB EVENT:${hubEvent.name}""")
                }
            }
        }
    }
    
    Log.i(TAG, "retrieving session status")
    
    // is user already authenticated (from a previous execution) ?
    Amplify.Auth.fetchAuthSession(
        { result ->
            Log.i(TAG, result.toString())
            val cognitoAuthSession = result as AWSCognitoAuthSession
            // update UI
            this.updateUserData(cognitoAuthSession.isSignedIn)
            when (cognitoAuthSession.identityId.type) {
                AuthSessionResult.Type.SUCCESS ->  Log.i(TAG, "IdentityId: " + cognitoAuthSession.identityId.value)
                AuthSessionResult.Type.FAILURE -> Log.i(TAG, "IdentityId not present because: " + cognitoAuthSession.identityId.error.toString())
            }
        },
        { error -> Log.i(TAG, error.toString()) }
    )

    若要驗證是否一切如預期,請建置專案。按一下 Build (建置) 功能表,然後選取 Make Project (製作專案),或者在 Mac 上,鍵入 ⌘F9。應不會發生錯誤。

    c.更新使用者界面程式碼

    程式碼中的最後變更與使用者界面相關,我們在主要活動中新增 FloatingActionButton

    在 res/layout 下,開啟 activity_main.xml 並使用以下項取代現有的 FloatingActionButton:

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fabAuth"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_baseline_lock"
        app:fabCustomSize="60dp"
        app:fabSize="auto"
        />

    在 res/drawable 下新增一個鎖形圖示。在 drawable 上按一下滑鼠右鍵,選取 New (新建),然後選取 Vector Asset (向量資產)。從美工圖案中選擇鎖形圖示,然後輸入 ic_baseline_lock (不帶 _24) 作為名稱,然後從美工圖案中選擇閉合的鎖形圖示。按一下 Next (下一步),然後按一下 Finish (完成)

    對打開的鎖形圖示重複相同的操作。

    之後,您應在可繪製目錄中包含以下檔案:

    現在,在程式碼中連結新建立的按鈕。在 java/com.example.androidgettingstarted/ 下,開啟 MainActivity.kt 並新增以下程式碼。

    // anywhere in the MainActivity class
    private fun setupAuthButton(userData: UserData) {
    
        // register a click listener
        fabAuth.setOnClickListener { view ->
    
            val authButton = view as FloatingActionButton
    
            if (userData.isSignedIn.value!!) {
                authButton.setImageResource(R.drawable.ic_baseline_lock_open)
                Backend.signOut()
            } else {
                authButton.setImageResource(R.drawable.ic_baseline_lock_open)
                Backend.signIn(this)
            }
        }
    }

    仍在 MainActivity 中,在 onCreate() 方法末尾新增以下程式碼

    setupAuthButton(UserData)
    
    UserData.isSignedIn.observe(this, Observer<Boolean> { isSignedUp ->
        // update UI
        Log.i(TAG, "isSignedIn changed : $isSignedUp")
    
        if (isSignedUp) {
            fabAuth.setImageResource(R.drawable.ic_baseline_lock_open)
        } else {
            fabAuth.setImageResource(R.drawable.ic_baseline_lock)
        }
    })

    上面的程式碼在 Userdata.isSignedIn 值上註冊了一位觀察者。當 isSignedIn 值變更時,將叫用閉合。現在,我們只需變更鎖形圖示:對使用者進行身份驗證時將其打開,而在沒有工作階段時將其閉合。

    若要驗證是否一切如預期,請建置專案。按一下 Build (建置) 功能表,然後選取 Make Project (製作專案),或者在 Mac 上,鍵入 ⌘F9。應不會發生錯誤。

    d.更新 AndroidManifest.xml 和 MainActivity

    最後,我們必須確保在 Cognito 託管的使用者界面所提供的 Web 身份驗證序列末尾,啟動我們的應用程式。我們在資訊清單中新增了一個新的活動。收到 gettingstarted URI 結構描述時將叫用該活動。

    在 Android Studio 中的資訊清單下,開啟 AndroidManifest.xml,然後將以下活動新增至應用程式元素。

        <activity
    android:name="com.amazonaws.mobileconnectors.cognitoauth.activities.CustomTabsRedirectActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
    
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
    
                <data android:scheme="gettingstarted" />
            </intent-filter>
        </activity>
    

    在 java/com.example.androidgettingstarted/ 下,開啟 MainActivity.kt 並在類別的任意位置新增以下程式碼。

    // MainActivity.kt
    // receive the web redirect after authentication
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        Backend.handleWebUISignInResponse(requestCode, resultCode, data)
    }

    在 java/com.example.androidgettingstarted/ 下,開啟 Backend.kt 並在類別的任意位置新增以下程式碼。

    // Backend.kt
    // pass the data from web redirect to Amplify libs 
    fun handleWebUISignInResponse(requestCode: Int, resultCode: Int, data: Intent?) {
        Log.d(TAG, "received requestCode : $requestCode and resultCode : $resultCode")
        if (requestCode == AWSCognitoAuthPlugin.WEB_UI_SIGN_IN_ACTIVITY_CODE) {
            Amplify.Auth.handleWebUISignInResponse(data)
        }
    }

    e.建置和測試

    若要驗證是否一切如預期,請建置並執行專案。按一下工具列中的 Run (執行) 圖示 ▶️,或鍵入 ^ R。應不會發生錯誤。該應用程式即會啟動,螢幕右下角出現一個閉合的鎖形浮動按鈕。

    這就是完整的註冊流程。

結論

現在,您已經使用幾行程式碼將使用者身份驗證功能新增到了您的應用程式中! 在下一個單元中,您將學習如何為應用程式新增 API。

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

新增 GraphQL API 和資料庫