开始使用SwiftUI的iOS认证(第一部分:登录和注销)

660 阅读28分钟

如果你是一名iOS开发者,对SwiftUI和Auth0的身份验证感到陌生,那么你就有机会了。在本教程中,你将在SwiftUI中构建一个应用程序,使用Auth0实现基本的登录和注销

本教程包括使用Auth0.swift SDK的2.0.0版本,在使用Swift编程语言和SwiftUI框架编写的iOS应用中实现登录/注销。在这个过程中,你将快速了解我们新修订的Swift SDK的基础知识,以及如何将其与苹果的SwiftUI框架一起使用。你还将熟悉Auth0仪表板,并学习如何使用它来注册应用程序和管理用户。

如果你想在关注构建和执行步骤的同时略过这些内容,请寻找🛠表情符号。

苹果的SwiftUI框架

SwiftUI logo

SwiftUI是一个用户界面工具包,也是苹果在2019年推出的构建应用程序的 "新方法"。通过SwiftUI,你可以使用Swift代码以声明的方式构建用户界面,这意味着你可以指定用户界面在不同的状态下应该如何看和表现。你不必指定用户界面如何在这些状态之间移动--它为你解决了这个问题。如果你知道React编程,你会发现SwiftUI很熟悉。

SwiftUI的方法与UIKit使用的方法完全不同,UIKit是iOS最初的UI工具箱,可以追溯到2007年。在UIKit中,你使用Interface Builder构建用户界面,这是一个拖放式布局工具,以图形方式构建应用程序的视图。你使用outlet和动作将UI元素与应用程序的视图控制器中的变量和方法连接起来。UIKit使用命令式方法,这意味着你要定义程序如何在各状态之间移动,以及UI在这些状态下的外观和行为。

Auth0和Auth0.swiftSDK

Auth0 logo

在应用程序中添加登录和注销似乎是一项简单的任务--直到你尝试。你必须处理多种登录方式,确认电子邮件地址和密码,管理用户,并处理安全性和可扩展性。每一个问题都有几十种考虑因素、风险、问题和边缘案例。

Auth0解决了这个问题。有了Auth0和几行代码,你的应用程序可以拥有一个全功能的系统,支持用用户名/密码组合登录、单点登录和社交账户、无密码登录、生物识别等。你也不必处理 "幕后 "的问题!相反,你可以专注于你的应用程序的主要功能。

Auth0.swift是所有苹果平台的Auth0 SDK:不仅是iOS,还有macOS、iPadOS、watchOS和tvOS。它是我们使用最多的第三个SDK,占到我们系统所有API请求的11%。如果你正在建立一个需要验证或授权其用户的苹果设备应用程序,你需要这个SDK!

Auth0.swift的最新版本,即2.0.0版,包含了我们在过去五年中从苹果设备上的应用安全中所获得的经验。如果你使用过早期版本,你会喜欢它更新的错误处理、对async/awaitCombine的支持、改进的默认配置、新的文档,以及我们删除了过时的方法和遗留功能。如果你是Auth0的新手,你会惊喜地发现,你只需要写很少的代码就可以在你的应用程序中添加认证。

你将建立什么

在本教程中,你将构建一个简单的、单屏幕的iOS应用,允许用户使用Auth0登录和注销。在登录时,屏幕将有不同的外观,并显示用户的姓名、电子邮件地址和他们个人资料中的照片。

你将从Xcode的菜单栏中选择文件项目......,而不是从一个启动项目中建立这个应用程序,你将从头开始建立它。

快速浏览该应用程序

当你启动完成的应用程序时,你会看到一个标志图标,一些状态文本,应用程序的标题,和一个登录按钮。

The app’s “Logged out” screen, featuring the app’s title, “SwiftUI Login Demo” and a “Log in” button.

登录按钮将用户带到Auth0通用登录界面,该界面出现在一个自定义的浏览器窗口中。

The Auth0 Universal Login web page, with Auth0 logo and “email address” and “password” fields.

当你使用Auth0为你的应用程序添加登录/注销功能时,你将认证委托给Auth0的通用登录,这是一个跨平台的基于webview的页面,支持登录、注册账户和其他认证流程。在这个练习中,你将使用默认的登录页面的 "外观和感觉",但你可以定制它以符合你的应用程序或组织的品牌

如果用户成功登录,"通用登录 "屏幕和它的浏览器窗口就会消失,用户就会回到应用中,这时会显示用户资料中的选定信息,即他们的资料照片、姓名和电子邮件地址,以及一个注销按钮。

The app’s “logged in” screen, featuring the text “Logged in” and displaying the user’s picture, name, and email address.

注销按钮将用户注销并返回到初始屏幕。

先决条件

以下是这个练习所需的软件、硬件和知识的清单。

一个Auth0账户

你将为本文的练习编写的应用程序使用Auth0来提供登录和注销功能。作为它的开发者,你需要一个Auth0账户。你可以注册一个免费账户,它允许你为多达10个应用程序和7000个用户添加认证。这对于评估该平台,以及原型设计、开发和测试来说,应该是足够了。

一个iOS开发设置

要为任何苹果硬件开发应用程序,你需要一台运行苹果集成开发环境Xcode的Mac电脑。

  • 2013年中期或以后的大多数Mac,至少有8GB内存(16GB为佳)。
  • 一个较新的macOS版本,最好是Big SurMonterey
  • Xcode11.0版(2019年9月)或更高版本。写这篇文章时,我使用了当前的版本:13.2.1(13C100)版本,于2021年12月17日发布。

一个iOS设备,虚拟或真实的

Xcode自带的模拟器是一个应用程序,可以创建虚拟设备,模拟iPhone、iPad和iPod Touch的最新型号,这些设备都运行iOS 15。

要为模拟器安装早期版本的iOS,从Xcode菜单中选择Preferences...,然后选择Components标签。你会看到一个旧版本的列表,不仅仅是iOS,还有watchOS和tvOS。

使用模拟器的好处之一是,你不需要一个苹果开发者账户--免费或付费--来使用它。

虽然模拟器很方便,但它不能替代实际的物理设备。它提供了更真实的测试体验,因为你不能在模拟器上做某些事情,如运动/倾斜感应和增强现实。

要将应用程序直接部署到设备上进行测试,你需要一个免费的苹果开发者账户,这又需要一个苹果ID。如果你没有Apple ID,请在这里注册一个。一旦你有了Apple ID,去developer.apple.com,点击页面顶部的 帐户在页面的顶部,然后登录。

你需要在你的开发者账户中注册设备,以便向其部署应用程序;你可以在苹果开发者网站的这个页面上这样做。每个会员年度你最多可以注册100台设备。你需要提供设备的UDID(唯一设备标识符),你可能会发现这个网站很有帮助。一旦你注册了一个设备,你就可以直接向其部署应用程序;见 将你的应用程序分发到注册设备上获取更多信息。

要将应用程序部署到App Store,你需要一个付费账户。欲了解更多详情,请参阅苹果开发者注册页面

要了解更多关于在虚拟和真实的iOS设备上运行应用程序的信息,请从苹果的文章开始。 在模拟器或设备上运行你的应用程序.

对Swift和structs有一定了解

虽然不是完全必要,但如果你熟悉Swift编程语言和iOS开发,会有所帮助。如果这些对你来说是新的,Swift编程语言,或UIKit框架,请尝试这个苹果教程。 今天就开始吧。.

SwiftUI在很大程度上依赖于struct,所以你可能会发现复习一下它们的基础知识很有帮助。你可能会发现Hacking with Swift 的文章。 如何创建你自己的结构的文章有帮助。

制作一个新的SwiftUI应用程序

让我们从构建一个新的SwiftUI应用开始。一旦我们有了一个基本的应用程序,并且你已经了解了一些SwiftUI界面元素,我们将纳入Auth0认证,然后通过添加一些用户体验的亮点来完成练习。

从头开始

🛠 启动Xcode,通过打开文件菜单并选择新建项目....,创建一个新项目。

Xcode将显示这个对话框,在这里你将为你要创建的应用程序选择一个项目模板。每个模板都会为不同的应用程序生成必要的文件,包括通用应用程序、视频游戏、增强现实应用程序以及为iMessage和Safari添加自定义功能的附加组件。

Xcode’s “Choose a template for your new project” dialog, with “iOS” and “App” selected.

🛠在这个练习中,我们想为iOS创建一个通用的应用程序,所以选择iOS标签,然后选择App项目模板,它将在集合的左上角。点击 "下一步"按钮来确认选择。

Xcode将显示下一个对话框,在这里你将给项目起一个对人类和计算机友好的名字,并指定你将使用哪种编程语言和框架。

Xcode’s “Choose options for your new project” dialog, with the  “Product Name” field filled with “SwiftUI Login Demo”.

🛠 在这个对话框中,做以下工作

  • 在 "产品名称 "栏中输入项目的名称。在这个练习中,我使用的名字是SwiftUI Login Demo
  • 团队菜单中选择一个团队。如果你还没有创建一个开发团队,并且想继续这个练习,而不经过注册苹果开发者账户和创建团队的过程,请选择。这将让你把应用程序部署到模拟器上,但不是部署到设备上。
  • 输入 com.example组织标识符字段中。
  • 界面菜单中选择SwiftUI
  • 语言菜单中选择Swift
  • 点击 "下一步"按钮。

🛠 Xcode将显示另外一个对话框--这个对话框让你指定你的项目及其文件的存储位置。选择一个位置。

一旦你完成了上面的步骤,Xcode将为你的项目生成文件并显示主窗口。

The Xcode window displaying the newly created project, with an empty Preview pane.

每当你使用App模板创建一个新的SwiftUI项目时,Xcode会生成一个名为ContentView 的单一视图,其内容是你在创建项目后看到的第一件事。

这是ContentView'的初始代码,上面有编号的注解。

import SwiftUI  // 1

// 2
struct ContentView: View {
  
  // 3
  var body: some View {
    
    // 4
    Text("Hello, world!")
      .padding()
  }
}

// 5
struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

下面是上面编号注释所标注的代码中发生的事情。

  1. 任何定义了UI元素的SwiftUI项目文件,无论是整个屏幕还是单个控件,都必须导入SwiftUI库。
  2. 在 SwiftUI 中,每个 UI 元素都是一个视图--一个采用View 协议的struct ,它定义了一个 SwiftUI 屏幕元素应该提供的功能。这个特殊的视图,ContentView ,定义了应用程序的单一屏幕。
  3. View 协议有一个要求:任何采用该协议的类型必须有一个body 属性,该属性定义了 UI 元素的外观和行为。body 属性的类型是some View ,这是Swift 表示 "某个采用View 协议的类型"的方式。请注意,body'的值是由闭包决定的,闭包是一个代码块,你可以传递给一个函数。
  4. 你可能已经明白了,Text 是一个在屏幕上显示文本的视图。视图后面可以有修改器--改变其外观或行为的方法。在这个例子中,我们用修改器在Text 视图的内容和边缘之间添加空间。 padding()修改器。
  5. 当Xcode为一个视图创建一个新文件时,它会生成两个struct:一个是出现在应用程序中的视图,一个是出现在Xcode编辑器中的预览。这个structContentView_Previews ,生成一个预览的ContentView ,让你看到它的样子,而不需要你编译和运行应用程序。

当编辑视图文件时,Xcode将其屏幕中央的编辑区域划分为两个区域:一个代码编辑器和一个预览浏览器。

🛠要看应用程序的用户界面是什么样子,从模拟器设备菜单中进行选择,然后点击预览查看器中的恢复按钮。

The Xcode window, with instructions to select a simulator device and click the “Resume” button.

你应该看到像这样的东西。

The Xcode window, with the Preview pane displaying a preview of the app.

🛠 你也可以选择通过运行该应用程序来看看它的运行情况。选择一个模拟器设备或将一个真实的设备连接到你的电脑,然后点击运行按钮。

The Xcode window, with instructions to make sure you’ve selected a simulator device and click the “Run” button.

模拟器将启动,你很快就会看到这个。

The Xcode simulator simulating an iPhone 13. Its screen is blank, except for the sentence “Hello, World!” in the center.

为应用程序添加状态和互动性

现在是时候让这个应用程序做更多的事情了,而不仅仅是显示 "你好,世界!"让我们创建该应用程序的两种状态--注销和登录--并为用户提供一种在它们之间导航的方法。

当启动时,该应用程序将具有标题文本和一个登录按钮。

The app’s “Logged out” screen, featuring the app’s title, “SwiftUI Login Demo” and a “Log in” button.

点击 "登录"按钮,你会进入这个屏幕,上面有 "已登录 "的文字和 "注销"按钮。

The app’s “Logged in” screen, featuring the text “Logged in” and a “Log out” button.

🛠在Xcode中,打开ContentView 文件,用下面的内容替换ContentView struct

struct ContentView: View {
  
  // 1
  @State private var isAuthenticated = false


  var body: some View {

    // 2
    if isAuthenticated {
      
      // 3
      VStack {
        
        Text("Logged in")
          .padding()
        
        // 4
        Button("Log out") {
          isAuthenticated = false
        }
        .padding()
        
      }
      
    } else {
    
      // 5
      VStack {
        
        Text("SwiftUI Login Demo")
          .padding()
        
        // 6
        Button("Log in") {
          isAuthenticated = true
        }
        .padding()
        
      }
      
    } // if isAuthenticated
    
  }
  
}

我在代码中标上了编号的注释,下面会有解释。

  1. 这一行声明了一个新的私有实例变量,isAuthenticated 。它以@State 开始,这告诉了SwiftUI关于它的一些事情。
    • @State 通知SwiftUI,该变量是视图状态的一部分,而视图状态是影响其外观和行为的变量集。当视图中任何状态变量的值发生变化时,SwiftUI会重新绘制视图以反映该变化。 的值将被设置为isAuthenticated true的值将被设置为:如果用户已登录,则为 false的值将被设置为用户已登录,而如果用户已注销。由于这个值会影响应用程序的外观,我把它变成了一个状态变量。
    • @State 也允许 '的方法来改变它的值。默认情况下,一个 '的方法不能改变其变量的值。struct struct
  2. 应用程序应根据isAuthenticated 的值来显示不同的屏幕。 if语句决定了将被分配给body 的值,这决定了屏幕上的用户界面。
  3. 这是语句的一个分支 if语句的分支,在用户登录的情况下执行。这个分支的结果必须是一个单一的视图,这是个问题:我们想显示两个视图:一些文本和注销按钮。为了解决这个限制,我们将使用一个视图作为其他视图的容器。VStack,其名称是 "垂直堆栈 "的简称。它最多可以容纳10个视图,以垂直列的形式显示,第一个视图出现在顶部,后面的视图出现在最顶部的视图下面。
  4. Button 视图需要两个参数。
    • 按钮的标签是一个字符串值。"Logged in"。
    • 一个闭包,定义了当用户按下按钮时应该发生的事情:它把isAuthenticated 的值改为 false.由于isAuthenticated 是一个状态变量,改变其值会导致SwiftUI重新绘制ContentView 。当这种情况发生时,应用程序将执行语句的另一个分支 if语句的另一个分支。
  5. 这是语句的分支 if语句的分支,如果用户没有登录就会执行。这个分支的结果是另一个VStack ,这个分支包含应用程序的标题和登录按钮。
  6. 这个Button 视图与登录按钮的视图类似,只是它写的是Log out,并在按下时将isAuthenticatedtrue当按下时。

🛠 如果 "恢复"按钮在预览窗格中是可见的,点击它。它将更新以显示新的用户界面。

🛠 运行该应用程序以查看其运行情况。点击登录注销按钮,从一个屏幕到另一个屏幕。

重构按钮的代码

随着SwiftUI视图变得越来越复杂,其代码往往变得越来越难读。保持其可读性的一个方法是将闭包中的代码放到它们自己的方法中。

🛠 将此扩展添加到ContentView ,在ContentViewContentView_Previews 之间。

extension ContentView {
  
  func login() {
    isAuthenticated = true
  }
  
  func logout() {
    isAuthenticated = false
  }
  
}

🛠 将ContentView 中的注销按钮的代码更新为以下内容。

        Button("Log out") {
          logout()
        }
        .padding()

🛠 将ContentView登录按钮的代码更新为以下内容。

        Button("Log in") {
          login()
        }
        .padding()

🛠 运行该应用程序。它仍将以同样的方式工作,但通过将按钮的闭包提取到自己的方法中,并将这些方法放到自己的扩展中,代码将更容易阅读和修改。

设置应用程序以与Auth0集成

现在你已经了解了一些 SwiftUI 视图,也看到了 SwiftUI 是如何使用状态来配置用户界面的,现在是时候将应用程序改为使用 Auth0 进行用户认证的应用程序了。

安装Auth0.swift

让我们来完成这项任务的第一部分:设置应用程序以与Auth0集成。我们将通过在项目中添加Auth0.swift包来实现这一目标。

Auth0.swift是一个库的集合,允许用Swift编写的应用程序利用Auth0的授权和认证功能。它包含这些Swift库。

有三种方法来安装Auth0.swift

  1. Swift Package Manager,苹果的依赖管理器
  2. Cocoapods,一个历史悠久的第三方软件包管理器,最早发布于2011年,在许多项目中使用
  3. Carthage,另一个第三方软件包管理器

我选择在本教程中使用Swift Package Manager,因为它内置在Xcode中,不需要额外的软件。如果你愿意使用Cocoapods或Carthage来安装Auth0.swift,请看这些说明

🛠 要开始安装Auth0.swift包的过程,打开文件菜单并选择添加包....会出现这个窗口。

The “Add Packages” window.

🛠 在窗口的搜索栏中输入Auth0.swift包库的URL。

https://github.com/auth0/Auth0.swift.git

Xcode将在线搜索并显示它在该URL中找到的任何包。搜索应该产生一个单一的结果。Auth0.swift

🛠 当Auth0.swift包出现在列表中时,选择它。在依赖关系规则菜单中,选择Up to Next Major Version,并确保其右边的文本字段中的版本号是os 2.0.0,然后点击添加包

The “Add Packages” window, with instructions for adding the “Auth0.swift” package.

🛠 你会被要求确认你想添加Auth0.swift包。点击 "添加软件包"来向Xcode保证,是的,你想要Auth0.swift。

The “Add Packages” window, with a modal window asking the user to select the packages to add.

Auth0.swift完成安装后,它的包将出现在项目屏幕的Package Dependencies标签下的列表中。你会看到Auth0.swift的库列在项目资源管理器窗格中。

Xcode’s “Package Dependencies” tab.

在这一点上,Auth0.swift所包含的功能现在对你的应用程序可用。一旦你完成了所有必要的Auth0设置,你将开始使用它。

添加一个属性列表来存储Auth0凭证

为了使用Auth0来验证用户,你的应用程序需要。

  • 与适当的Auth0租户通信,并且
  • 向该服务器识别自己。

你通过向应用程序提供该租户的标识符,一个被称为的值,以及应用程序的标识符,即客户端ID来实现这一目的。Auth0.swift希望能在一个属性列表(一个 .plist文件)中找到这些值,所以我们来创建一个。

🛠 右键单击(或控制单击)项目资源管理器中的SwiftUI Login Demo文件夹,选择**"新文件**",创建一个新的属性列表文件...。

Xcode screenshot, showing the user selecting “File -> New File...”

🛠 在出现的窗口中,确保选择iOS标签。向下滚动图标列表,直到你看到属性列表图标。选择它,然后点击下一步

Xcode screenshot, showing the selection of the “Property List” file template.

🛠 命名该文件 Auth0.plist并点击Create来创建该文件。

Xcode screenshot, showing the “Save” dialog box for the property list.

Xcode将以表格的形式显示新的 Auth0.plist文件以表格的形式显示。让我们在表中添加两行,这将容纳域和客户ID值。

🛠 将光标移到根行上,显示出**"+**"按钮。点击两次 "+"按钮,增加两行

Xcode screenshot, showing the creation of two new rows in the property list.

🛠 在这两行中输入以下值

  • 第1行
    • 键: Domain
    • 类型: String
    • 值:暂时留空。你将从Auth0仪表板上得到这个值。
  • 第2行
    • 钥匙: ClientId
    • 类型: String
    • 值:暂时留空。你将从Auth0仪表板上得到这个值。

你的Auth0 plist文件应该看起来像这样。

Xcode screenshot, showing the completed property list.

设置Auth0以与你的应用程序整合

现在你已经设置了应用程序与Auth0一起工作,现在是时候设置你的Auth0租户与该应用程序一起工作了。为了实现这一目标,你要做以下工作。

  1. 将该应用添加到你的Auth0仪表板的注册应用列表中
  2. 收集两个信息,应用程序将需要把登录/注销委托给Auth0。
    • 你的租户的域名
    • Auth0将分配给该应用程序的客户ID
  3. 向Auth0提供必要的回调URL以联系该应用:一个是在登录过程结束时调用,另一个是在注销过程结束时调用。

你需要一个Auth0账户来完成这一步。再一次,你可以免费注册一个Auth0账户我们已经非常小心地使这个过程尽可能地无痛。

将应用程序添加到应用程序列表中

🛠 登录Auth0仪表板,从页面左侧的菜单中选择应用应用

现在你将进入 "应用程序"页面,其中列出了你在Auth0注册的所有应用程序。让我们把你的应用程序添加到列表中。

🛠 点击页面右上方的创建应用程序按钮,开始注册新应用程序的过程。

The “Applications” page. The reader is directed to click the “Create Application” button.

你会看到这个对话框出现。

The “Create application” dialog. The application’s name is set to “iOS Auth”, and the selected application type is “Native”.

🛠 你需要提供两个信息才能继续。

  • 在名称栏中输入一个应用程序的名称。可能最简单的是使用与你的Xcode项目相同的名称(如果你一直在遵循我的例子,使用SwiftUI Login Demo这个名称)。
  • 指定应用程序的类型,在这种情况下,它是Native

🛠 点击创建。应用程序的快速启动页面将出现。

The “Quick Start” page. It contains several icons, each one representing an operating system or platform.

这个页面为你提供了几个不同平台的现成项目,你可以将其作为将认证委托给Auth0的应用程序的基础。在这个练习中,你不会使用它们中的任何一个;相反,你将利用几个Auth0库并自己编写代码。这样做更有教育意义,更重要的是,更有乐趣

🛠 单击 "设置"选项卡,这将带你到这个页面。

The “Application” page’s “Settings” tab.

你要在这个页面上做两件关键的事情。

  1. 获取应用程序需要知道的关于Auth0的信息,以及
  2. 提供Auth0需要知道的关于该应用的信息。

让我们来处理第一件事。获取应用程序需要的信息,即域名和客户ID,你将把它们输入你先前创建的属性列表文件中。

🛠 复制Domain字段的内容,然后切换到Xcode,打开Auth0 属性列表,并将你复制的Domain值粘贴到Domain行的Value字段。

🛠 接下来,回到Auth0仪表板,复制Client ID字段的内容,然后切换到Xcode,将你复制的域值粘贴到属性列表中的ClientId行的Value字段。

The Auth0 property list in Xcode, with instructions to copy and paste the “Domain” and “Client ID” values into it.

🛠 返回到Auth0仪表板,向下滚动到应用程序URI部分。

The “Application URIs” section of the “Application” page’s “Settings” tab.

这是你向Auth0提供它需要知道的关于你的应用程序的两个信息的地方。

  1. **回调URL:**用户成功登录后Auth0将重定向到的URL。可以有不止一个这样的URL。
  2. **注销URL:**用户注销后Auth0将重定向到的URL。可以有多个。

在这一点上,你可能在想。"等一下--我在用SwiftUI写一个iOS应用。它没有你用URL导航到的网页,而是视图!"

你说得很对。对于原生应用程序,回调和注销URL是同一个字符串,Auth0将该字符串发送给应用程序,以通知它用户已经登录或注销。

本机iOS应用程序用于回调URL和注销URL的字符串都遵循这种格式。

{BUNDLE_IDENTIFIER}://{YOUR_DOMAIN}/ios/{BUNDLE_IDENTIFIER}/callback

要构建这个字符串,你需要你的应用程序的捆绑标识符。

🛠在Xcode中,点击项目导航器中的项目,在Targets菜单中点击项目,并选择General标签。复制捆绑标识符的值,你可以在中心窗格顶部附近的身份部分的捆绑标识符字段中找到它。

Getting the bundle identifier from Xcode.

🛠 复制上面的URL格式字符串,并进行以下修改,以创建一个新的URL。

  • {BUNDLE_IDENTIFIER}替换为你复制的捆绑标识符。注意 {BUNDLE_IDENTIFIER}在URL中出现两次--两次都要替换。
  • 替换为 {YOUR_DOMAIN}用你的租户的域名。

🛠 在允许回调URLs允许登录URLs字段中输入你刚刚构建的URL。记住,两个字段都要输入相同的URL。

The “Application URIs” section of the page. The reader is directed to enter the callback URL into “Allowed Callback URLs” and “Allowed Logout URLs”.

🛠 你已经完成了本页需要做的一切。向下滚动到页面的底部,点击保存更改按钮。

The bottom of the page, which features the “Save Changes” button. An arrow directs the reader to click the button.

如果你的租户没有任何用户,请创建一个用户

如果你刚刚创建了一个Auth0账户,你的租户就不会有任何用户账户。你至少需要一个用户账户才能登录到应用程序。按照这些步骤创建一个用户。

🛠 在Auth0仪表板左侧的菜单中,选择用户管理用户

The bottom of the page now featuring an expanded “User Management” menu. An arrow directs the reader to expand the “Users” menu item.

将出现 "用户"页面。它列出了所有注册到你租户的用户。如果没有用户,你会看到 "你还没有任何用户 "的信息。

The “Users” page. The page says, “You don’t have any users yet”. An arrow directs the reader to click the “Create User” button.

🛠 单击 "创建用户"按钮,创建一个新用户,这将使这个对话框出现。

The “Create User” dialog. It has fields for email and password, as well as a drop-down menu displaying “Username-Password-Authentication”.

🛠 为用户输入一个电子邮件地址和密码。连接的唯一选项将是用户名-密码-认证,所以保持原样。记下这个电子邮件地址和密码--你将用它们来登录应用程序。

🛠 点击创建按钮来创建用户。该用户的详细信息页面将出现。

The user’s “Details” page.

这就解决了你在Auth0仪表板上需要做的所有设置。现在是时候回到Xcode和应用程序中去了。

添加认证

随着所有设置的完成,是时候回到编码中了。在这一步中,我们将把应用程序转换为一个使用Auth0来记录用户进出的应用程序。

导入Auth0库

🛠 在ContentView 的开头附近找到这一行 ...

import SwiftUI

...并在后面添加这个 import语句紧随其后。

import Auth0

这一补充将使应用程序能够使用Auth0 对象及其方法和属性。

更新 login()方法

login()方法只是模拟了登录过程。让我们把它变成现实。

🛠 打开ContentView ,将当前的 login()方法,用这个方法取代当前的方法。

  func login() {
    Auth0 // 1
      .webAuth() // 2
      .start { result in // 3
        switch result {
          // 4
          case .failure(let error):
            print("Failed with: \(error)")
          // 5
          case .success(let credentials):
            self.isAuthenticated = true
            print("Credentials: \(credentials)")
            print("ID token: \(credentials.idToken)")
        } 
      }
  }

下面的注释与login()方法中的编号注释相对应。

  1. Auth0包的Auth0 对象为认证过程提供了方法。这些方法中的许多都是执行认证的一个必要步骤,你可以把这些方法连锁起来,以完成不同的认证任务。
  2. webAuth()是该链中的第一个方法。它创建了一个WebAuth 对象,启动了通用登录。它需要租户的域名和应用程序的客户端ID,它从Auth0 属性列表中收集这些信息。
  3. start()是呈现登录框的方法。它接受一个闭包,其唯一的参数代表用户尝试登录的结果。两个可能的结果--登录失败和登录成功--都在闭包中处理。
  4. 我们在失败的情况下保持简单。在登录不成功的情况下,应用程序只是在调试控制台上打印出一条错误信息。
  5. 如果用户成功登录,会发生两件事。
    • 应用程序接收用户的凭证,这是一个关于用户的信息集合。其中一个凭证是ID令牌,它是用户已被验证的证明。目前,该应用程序将简单地使用credentials'idToken 属性将ID令牌打印到调试台;在以后的修订中,它将从令牌中提取用户的姓名、电子邮件地址和图片URL。
    • isAuthenticated 状态变量被设置为 true,这一变化导致 UI 更新为 "已登录 "视图。

更新 logout()的方法

就像你对 login()所做的那样,现在是时候给这个 logout()方法的真正功能。

🛠用这个方法替换当前的 logout()方法替换为这个方法。

  func logout() {
    Auth0 // 1
      .webAuth() // 2
      .clearSession { result in // 3
        switch result {
          // 4
          case .failure(let error):
            print("Failed with: \(error)")
            // 5
          case .success:
            self.isAuthenticated = false
        }
      }
  }

下面的注释与logout()方法中的编号注释相对应。

  1. 我们再次从Auth0 对象中链入方法。
  2. 就像在 login(), webAuth()是链条中的第一个方法,我们再次用它来激活通用登录。
  3. clearSession()完成注销的实际工作。就像 start()中的方法 login(), clearSession()中的方法一样,需要一个带有单个参数的闭包,代表该请求的结果。
  4. 如同 login()中的方法一样,如果系统不能将用户注销,应用程序只是打印出一条错误信息。
  5. 如果用户成功注销,isAuthenticated 状态变量被设置为 false,这一变化导致用户界面更新为 "已注销 "视图。

测试更新后的应用程序

🛠 运行应用程序,以确认该应用程序确实能验证用户。这一次,当你按下登录按钮时,不是直接进入 "已登录 "视图,而是看到通用登录屏幕。你需要输入一个有效的用户名和密码才能看到这第二个屏幕。

在你登录后看一下Xcode的调试窗口。你会看到这个方法的 login()方法的 print()函数的输出,它输出了credentials 对象的内容和它的idToken 属性。

Credentials: Credentials(accessToken: "<REDACTED>", tokenType: "Bearer", idToken: "<REDACTED>", refreshToken: nil, expiresIn: 2022-03-20 04:38:25 +0000, scope: Optional("openid profile email"), recoveryCode: nil)
ID token: eyJhbGciOiJSUzI1NiIsInR5cC...

注意,当 print()函数用来输出credentials 的内容时,accessTokenidToken 属性的值被替换为字符串 <REDACTED>.理想情况下,你应该在应用程序进入 print()函数,但许多开发者经常忘记这一步骤。恶意的一方可以使用工具来捕获生产应用程序中的 print()函数的输出;这就是为什么Credentials 实例在打印时要编辑其accessTokenidToken 属性的值。

credentials 有一个 属性,包含一个以空格分隔的scope OpenID Connect(OIDC)作用域列表--用于访问有关用户的详细信息的授权--Auth0已经授予该应用程序。除非你另外指定,Auth0.swift默认在登录用户时请求以下作用域。

  • openid:授权使用OIDC来验证用户的身份
  • profile:授权访问用户的姓名信息
  • email:授权访问用户的电子邮件地址

为了确认应用程序在登录用户后收到了一个ID令牌,我们打印它的值。我们将在下一步用它来获取用户的姓名、电子邮件地址和图片。

警告:🚨当你在学习认证过程或构建应用程序时,将ID令牌的值打印到调试控制台是没有问题的。请确保你删除 print()语句--特别是那些打印敏感信息的语句,如ID令牌--在投入生产之前

到目前为止,你已经创建了一个基于SwiftUI的iOS应用,它使用Auth0来实现基本的登录和注销功能。在本教程的第二部分,你将赋予该应用获取登录用户的信息并在屏幕上显示的能力。