【译】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.

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


相关推荐
QuantumLeap丶16 小时前
《Flutter全栈开发实战指南:从零到高级》- 26 -持续集成与部署
android·flutter·ios
2501_9159184119 小时前
TCP 抓包分析在复杂网络问题中的作用,从连接和数据流层面理解系统异常行为
网络·网络协议·tcp/ip·ios·小程序·uni-app·iphone
二流小码农20 小时前
鸿蒙开发:个人开发者如何使用华为账号登录
android·ios·harmonyos
wvy1 天前
Xcode 26还没有适配SceneDelegate的app建议尽早适配
ios
游戏开发爱好者81 天前
苹果 App 上架流程,结合 Xcode、CI 等常见工具
macos·ios·ci/cd·小程序·uni-app·iphone·xcode
前端老白1 天前
webview在微信小程序中,安卓加载失败,IOS正常加载
android·ios·微信小程序·webview
2501_915106321 天前
用 HBuilder 上架 iOS 应用时如何管理Bundle ID、证书与描述文件
android·ios·小程序·https·uni-app·iphone·webview
2501_915909061 天前
资源文件混淆在 iOS 应用安全中的实际价值
android·安全·ios·小程序·uni-app·iphone·webview
2501_915918411 天前
iOS App 性能测试中常被忽略的运行期问题
android·ios·小程序·https·uni-app·iphone·webview
Name_NaN_None1 天前
iPhone怎么投屏到电脑上?
ios·电脑·iphone