【译】iOS 用 ASWebAuthenticationSession 实现 OAuth 登录(四)- 令牌(TOKEN)相关

原文链接:Implementing OAuth with ASWebAuthenticationSession | Kodeco


iOS 用 ASWebAuthenticationSession 实现 OAuth 登录

理解令牌

登录时,用户现在可以获得一个授权码。尽管如此,这还不是终点。 该访问码的持续有效期间很短,并且只能被使用一次。 目的是为了用它交换访问令牌和刷新令牌。

正如之前你看到的,访问令牌在你每次发送请求时都会带上以授权请求。刷新令牌的存活期间更长。 你可以在当前的访问令牌过期时用刷新令牌来获取一个新的访问令牌。

处理令牌

使用手中的授权码,现在可以用它来交换令牌了。 你也会在 App 中添加逻辑来正确地处理它们。

打开 NetworkRequest.swift

start(responseType:completionHandler:) 中的紧接着以下代码:

swift 复制代码
guard 
  error == nil,
  let data = data
else {
  DispatchQueue.main.async {
    let error = error ?? NetworkRequest.RequestError.otherError
    completionHandler(.failure(error))
  }
  return
}

找到代码行:

swift 复制代码
if let object = try? JSONDecoder().decode(responseType, from: data) {

将该行替换为以下代码:

swift 复制代码
// 1
if T.self == String.self,
  let responseString = String(data: data, encoding: .utf8) {
  // 2
  let components = responseString.components(separatedBy: "&")
  var dictionary: [String: String] = [:]
  // 3
  for component in components {
    let itemComponents = component.components(separatedBy: "=")
    if let key = itemComponents.first,
       let value = itemComponents.last {
      dictionary[key] = value
    }
  }
  // 4
  DispatchQueue.main.async {
    // 5
    NetworkRequest.accessToken = dictionary["access_token"]
    NetworkRequest.refreshToken = dictionary["refresh_token"]
    completionHandler(.success((response, "Success" as! T)))
  }
  return
} else if let object = try? JSONDecoder().decode(T.self, from: data) {

令牌交换响应会返回一个字符串,但是其它 GitHub API 响应是JSON格式的。 这里就是如何处理这种情况:

  1. 添加该语句,首先会看到有一个字符串响应作为内容。
  2. 该响应字符串,里面包含令牌,是用 & 分隔开的多个键值对,这也是将字符串分割成键值对数组的原因。
  3. 循环 components 的各个元素得到响应的 Swift 字典。
  4. 由于 URLSession 的默认线程模型,现在所有的处理都是在后台运行。因此,要调用 DispatchQueue 来唤醒主线程中的下一步处理。需要这么做的原因是完成处理器只会在主线程完成后更新 UI 。
  5. 该代码块在 NetworkRequest 的两个辅助属性中存储了访问令牌和更新令牌。然后会调用完成处理器,提示处理已经成功。

NetworkRequest 如何处理令牌。

要想看一下 NetworkRequest 对令牌作了什么处理,要的到 NetworkRequest+User.swift

它们是 String 类型的属性,在这背后它们向 UserDefaults 读写令牌,这样可以在 App 启动后保持。

这些令牌属于敏感数据,所以在你的 App 中,所以在 App 中,你想要确保它们安全地存储在 钥匙链中。 这是一个很有意思的课题,你可以在 如何保护 iOS 用户数据:SwiftUI 中的钥匙链服务和生物识别技术 了解到更多内容。

编译运行。登录。模态控制器会再次在屏幕上闪一下,之后你就可以看到你的代码仓库的列表了:

太棒了!

创建短暂 SESSION (会话)

最后一个课题涉及的是短暂会话 ,它是私有的认证会话。 短暂会话不会向磁盘缓存会话相关的数据,而是缓存在 RAM 中。 会话过期后,短暂会话 会清空会话数据。 这会很方便赋予用户添加的隐私信息和安全信息。

打开 SignInViewModel.swift 。 在 signInTapped 中以下代码的下面:

swift 复制代码
authenticationSession.presentationContextProvider = self

添加以下代码:

swift 复制代码
authenticationSession.prefersEphemeralWebBrowserSession = true

这会避免前面遇到的在第二次或第三次尝试在APP启动后快速登录时不提示输入用户凭证的问题。 短暂会话意味着 ASWebAuthenticationSession 不会缓存所有信息,并总会在会话开始时向客户询问凭证。

编译运行。

你仍是已登录的状态,因为 App 保存了访问令牌和刷新令牌。 点击顶部的 Sign Out 以清空令牌。 现在,尝试登录时,会提示要输入你的 GitHub 用户名和密码。 App 不会缓存任何之前登录的令牌,因为这是私有会话。

优秀!这看上去像是一个小问题,但对于安全方面,会有很大好处。

接下来要做什么?

可以点击该指南顶部或底部的 Download Materials 下载完整的工程文件。

做得很好!在该指南中,你学到了OAuth 的相关介绍,然后创建了你自己的使用 ASWebAuthenticationSession 授权的 GitHub App。 可以尝试添加一些特性,如把令牌存储在钥匙串中加强存储令牌的方式,和添加更多的 GitHub API 请求。

如果想阅读关于OAuth的更多令牌,访问 IETF页面,它包含整个标准。 内容有些繁多,但是是很好的参考资料。

想了解 ASWebAuthenticationSession 的细节和文档,访问Apple 开发者文档

想看在线视频课的话,查看 Networking with URLSession.

如果有任何问题或建议,不要犹豫,在下面的论坛中与我们联系。


相关推荐
游戏开发爱好者822 分钟前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
黑码哥43 分钟前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
2501_915106322 小时前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview
2501_915106322 小时前
使用 Sniffmaster TCP 抓包和 Wireshark 网络分析
网络协议·tcp/ip·ios·小程序·uni-app·wireshark·iphone
熊猫钓鱼>_>3 小时前
移动端开发技术选型报告:三足鼎立时代的开发者指南(2026年2月)
android·人工智能·ios·app·鸿蒙·cpu·移动端
徐同保1 天前
通过ip访问nginx的服务时,被第一个server重定向了,通过设置default_server解决这个问题
ios·iphone
2501_915918411 天前
在 iOS 环境下查看 App 详细信息与文件目录
android·ios·小程序·https·uni-app·iphone·webview
2501_916007471 天前
没有 Mac 用户如何上架 App Store,IPA生成、证书与描述文件管理、跨平台上传
android·macos·ios·小程序·uni-app·iphone·webview
夏幻灵2 天前
HTTPS全面解析:原理、加密机制与证书体
ios·iphone
TheNextByte12 天前
如何在iPhone上恢复已删除的笔记的综合指南
笔记·ios·iphone