MST

星途 面试题库

面试题:Swift的URLSession如何处理复杂的认证机制

假设服务器采用OAuth 2.0认证机制,在Swift中利用URLSession实现对受保护资源的访问,描述整体实现思路并给出关键代码片段。
16.2万 热度难度
编程语言Swift

知识考点

AI 面试

面试题答案

一键面试

整体实现思路

  1. 获取授权码
    • 构造授权请求URL,该URL包含客户端ID、重定向URI、响应类型(通常为code)等参数。
    • 在应用中打开该URL(通常通过UIApplication.shared.open),用户在授权服务器界面进行登录和授权操作。
    • 授权成功后,授权服务器将授权码通过重定向URI返回给应用。
  2. 用授权码换取访问令牌
    • 构造令牌请求,通常是一个HTTP POST请求,包含授权码、客户端ID、客户端密钥、重定向URI和授予类型(authorization_code)等参数。
    • 使用URLSession发送该请求到授权服务器的令牌端点。
    • 授权服务器验证请求后,返回访问令牌、刷新令牌(可选)等信息。
  3. 使用访问令牌访问受保护资源
    • 构造对受保护资源的请求URL。
    • 在请求头中添加Authorization字段,其值为Bearer 加上访问令牌。
    • 使用URLSession发送该请求到受保护资源的端点,获取资源数据。

关键代码片段

  1. 获取授权码(构造并打开授权URL)
let clientID = "your_client_id"
let redirectURI = "your_redirect_uri"
let authURLString = "https://authorization_server.com/authorize?response_type=code&client_id=\(clientID)&redirect_uri=\(redirectURI)"
if let authURL = URL(string: authURLString) {
    UIApplication.shared.open(authURL, options: [:], completionHandler: nil)
}
  1. 用授权码换取访问令牌
let code = "the_received_authorization_code"
let clientID = "your_client_id"
let clientSecret = "your_client_secret"
let redirectURI = "your_redirect_uri"
let tokenURL = URL(string: "https://authorization_server.com/token")!
var tokenRequest = URLRequest(url: tokenURL)
tokenRequest.httpMethod = "POST"
let parameters = "grant_type=authorization_code&code=\(code)&client_id=\(clientID)&client_secret=\(client_secret)&redirect_uri=\(redirectURI)"
tokenRequest.httpBody = parameters.data(using:.utf8)
tokenRequest.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

let task = URLSession.shared.dataTask(with: tokenRequest) { data, response, error in
    guard let data = data, error == nil else {
        print(error?.localizedDescription ?? "No data")
        return
    }
    if let tokenResponse = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
        let accessToken = tokenResponse["access_token"] as? String
        print("Access Token: \(accessToken ?? "Not found")")
    }
}
task.resume()
  1. 使用访问令牌访问受保护资源
let accessToken = "the_received_access_token"
let resourceURL = URL(string: "https://protected_resource.com/resource")!
var resourceRequest = URLRequest(url: resourceURL)
resourceRequest.httpMethod = "GET"
resourceRequest.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

let task = URLSession.shared.dataTask(with: resourceRequest) { data, response, error in
    guard let data = data, error == nil else {
        print(error?.localizedDescription ?? "No data")
        return
    }
    if let resourceResponse = String(data: data, encoding:.utf8) {
        print("Resource: \(resourceResponse)")
    }
}
task.resume()