AWS 入門

建置 iOS 應用程式

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

單元 3:新增身份驗證

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

簡介

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

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

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

您將學到的內容

  • 建立和部署身份驗證服務
  • 設定您的 iOS 應用程式以包括 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 iosgettingstartedfc5a4717 locally
  • 部署身份驗證服務

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

    amplify push
    
    # press Y when asked to continue

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

    ✔ All resources are updated in the cloud
    
    Hosted UI Endpoint: https://iosgettingstarted-dev.auth.eu-central-1.amazoncognito.com/
    Test Your Hosted UI Endpoint: https://iosgettingstarted-dev.auth.eu-central-1.amazoncognito.com/login?response_type=code&client_id=1234567890&redirect_uri=gettingstarted://
  • 將 Amplify 身份驗證程式庫新增至專案

    在前往程式碼之前,您需要將 Amplify 身份驗證程式庫新增至專案的相依項中。開啟 Podfile 檔案,然後使用 AmplifyPlugins/AWSCognitoAuthPlugin 新增行,或複製/貼上下面的整個檔案

    # you need at least version 13.0 for this tutorial, more recent versions are valid too
    platform :ios, '13.0'
    
    target 'getting started' do
      # Comment the next line if you don't want to use dynamic frameworks
      use_frameworks!
    
      # Pods for getting started
      pod 'Amplify', '~> 1.0'                             # required amplify dependency
      pod 'Amplify/Tools', '~> 1.0'                       # allows to call amplify CLI from within Xcode
    
      pod 'AmplifyPlugins/AWSCognitoAuthPlugin', '~> 1.0' # support for Cognito user authentication
    
    end

    在終端機中,執行以下命令:

    pod install

    該命令需要幾秒鐘即可完成。您應看到以下資訊 (實際版本編號可能會有所差異):

    Analyzing dependencies
    Downloading dependencies
    Installing AWSAuthCore (2.14.1)
    Installing AWSCognitoIdentityProvider (2.14.1)
    Installing AWSCognitoIdentityProviderASF (1.0.1)
    Installing AWSCore (2.14.1)
    Installing AWSMobileClient (2.14.1)
    Installing AWSPluginsCore (1.0.4)
    Installing AmplifyPlugins (1.0.4)
    Generating Pods project
    Integrating client project
    Pod installation complete! There are 3 dependencies from the Podfile and 8 total pods installed.
  • 在執行時間設定 Amplify 身份驗證程式庫

    返回 Xcode,開啟 Backend.swift 檔案。在後端類別中,

    • 新增 AmplifyPlugins 的匯入語句
    • 向我們在上一部分新增的 Amplify 初始化程式碼新增一行

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

    // at the top of the file
    import AmplifyPlugins
    
    private init () {
      // initialize amplify
      do {
         try Amplify.add(plugin: AWSCognitoAuthPlugin())
         try Amplify.configure()
         print("Initialized Amplify")
      } catch {
         print("Could not initialize Amplify: \(error)")
      }
    }

    若要驗證是否一切如預期,請建置專案。按一下 Product (產品) 功能表,然後選取 Build (建置) 或輸入 ⌘B。應不會發生錯誤。

  • 在執行時間觸發身份驗證

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

    a.新增登入和登出程式碼。在後端類別中的任意位置,新增以下三種方法:

     

    // MARK: - User Authentication
    
    // signin with Cognito web user interface
    public func signIn() {
    
        _ = Amplify.Auth.signInWithWebUI(presentationAnchor: UIApplication.shared.windows.first!) { result in
            switch result {
            case .success(_):
                print("Sign in succeeded")
            case .failure(let error):
                print("Sign in failed \(error)")
            }
        }
    }
    
    // signout
    public func signOut() {
    
        _ = Amplify.Auth.signOut() { (result) in
            switch result {
            case .success:
                print("Successfully signed out")
            case .failure(let error):
                print("Sign out failed with error \(error)")
            }
        }
    }
    
    // change our internal state, this triggers an UI update on the main thread
    func updateUserData(withSignInStatus status : Bool) {
        DispatchQueue.main.async() {
            let userData : UserData = .shared
            userData.isSignedIn = status
        }
    }

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

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

    收到身份驗證事件後,我們將叫用 updateUserData() 方法。此方法使 UserData 物件保持同步。UserData.isSignedIn 屬性為 @Published,表示值變更時會自動重新整理使用者界面。 

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

    在 Backend.init() 中,在 Amplify 初始化之後新增以下程式碼

    // in private init() function
    // listen to auth events.
    // see https://github.com/aws-amplify/amplify-ios/blob/master/Amplify/Categories/Auth/Models/AuthEventName.swift
    _ = Amplify.Hub.listen(to: .auth) { (payload) in
    
        switch payload.eventName {
    
        case HubPayload.EventName.Auth.signedIn:
            print("==HUB== User signed In, update UI")
            self.updateUserData(withSignInStatus: true)
    
        case HubPayload.EventName.Auth.signedOut:
            print("==HUB== User signed Out, update UI")
            self.updateUserData(withSignInStatus: false)
    
        case HubPayload.EventName.Auth.sessionExpired:
            print("==HUB== Session expired, show sign in UI")
            self.updateUserData(withSignInStatus: false)
    
        default:
            //print("==HUB== \(payload)")
            break
        }
    }
     
    // let's check if user is signedIn or not
     _ = Amplify.Auth.fetchAuthSession { (result) in
         do {
             let session = try result.get()
                    
    // let's update UserData and the UI
         self.updateUserData(withSignInStatus: session.isSignedIn)
                    
         } catch {
              print("Fetch auth session failed with error - \(error)")
        }
    }    

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

    程式碼中的最後變更與使用者界面相關,我們將 ZStack 新增至 ContentView。根據 UserData.isSignedIn 的值,UI 會顯示 SigninButton 或主要清單檢視。

    開啟 ContentView.swift 並取代 ContentView 結構中的主體︰

    var body: some View {
    
        ZStack {
            if (userData.isSignedIn) {
                NavigationView {
                    List {
                        ForEach(userData.notes) { note in
                            ListRow(note: note)
                        }
                    }
                    .navigationBarTitle(Text("Notes"))
                    .navigationBarItems(leading: SignOutButton())
                }
            } else {
                SignInButton()
            }
        }
    }

    在同一檔案中,新增 SignInButton 和 SignOutButton 檢視:

    struct SignInButton: View {
        var body: some View {
            Button(action: { Backend.shared.signIn() }){
                HStack {
                    Image(systemName: "person.fill")
                        .scaleEffect(1.5)
                        .padding()
                    Text("Sign In")
                        .font(.largeTitle)
                }
                .padding()
                .foregroundColor(.white)
                .background(Color.green)
                .cornerRadius(30)
            }
        }
    }
    
    struct SignOutButton : View {
        var body: some View {
            Button(action: { Backend.shared.signOut() }) {
                    Text("Sign Out")
            }
        }
    }

    若要驗證是否一切如預期,請建置專案。按一下 Product (產品) 功能表,然後選取 Build (建置) 或輸入 ⌘B。應不會發生錯誤。

    d.更新 Info.plist

    最後,我們必須確保在 Cognito 託管的使用者界面所提供的 Web 身份驗證序列末尾,啟動我們的應用程式。我們將入門 URI 方案新增至應用程式的 Info.plist 檔案中。

    在 Xcode 中,選取 Info.plist 檔案,按一下滑鼠右鍵,然後選取Open As, Source Code (以來源程式碼開啟)

    iOSTutorial-Module3-step1

    上方 <dict> 元件內新增下面 <key> 和 <array> 元件。

    <plist version="1.0">
    
        <dict>
        <!-- YOUR OTHER PLIST ENTRIES HERE -->
    
        <!-- ADD AN ENTRY TO CFBundleURLTypes for Cognito Auth -->
        <!-- IF YOU DO NOT HAVE CFBundleURLTypes, YOU CAN COPY THE WHOLE BLOCK BELOW -->
        <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>gettingstarted</string>
                </array>
            </dict>
        </array>
    
        <!-- ... -->
        </dict>

    e.建置和測試

    若要驗證是否一切如預期,請建置專案。按一下 Product (產品) 功能表,然後選取 Run (執行) 或輸入 ⌘R。應不會發生錯誤。該應用程式即會按下 Sign In (登入) 按鈕時啟動。

    這就是完整的註冊流程︰

    iOSTutorial-Module3-step2
    iOSTutorial-Module3-step5
    iOSTutorial-Module3-step3
    iOSTutorial-Module3-step6
    iOSTutorial-Module3-step4
    iOSTutorial-Module3-step7

結論

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

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

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

新增 GraphQL API 和資料庫