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