Alamofire是可用于iOS和Mac项目的流行框架。它使网络实施变得容易,并允许我们使用RequestAdapter进行身份验证来对请求签名。
对身份验证请求签名
API通常要求您使用结合Authorization请求头的JSON Web令牌来签名请求。每个外发请求都需要设置该身份验证请求头才能被后端接受。
Alamofire中的RequestAdapter
Alamofire带有两个协议,RequestAdapter
和和RequestRetrier
。
RequestAdapter:
可以在必要时以某种方式检查和可选地调整URLRequest的类型。
RequestRetrier:
一种类型,用于确定在由指定的会话管理器执行并遇到错误之后是否应重试请求。
两者的结合可能是实现身份验证系统的理想方法。如果由于身份验证原因请求失败,则可以使用RequestRetrier
刷新身份验证令牌并触发重试。使用RequestAdapter
您可以为每个传出请求设置身份验证头。
创建一个请求适配器
首先,您需要创建自己的请求适配器类。
final class JWTAccessTokenAdapter: RequestAdapter {
typealias JWT = String
private let accessToken: JWT
init(accessToken: JWT) {
self.accessToken = accessToken
}
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
var urlRequest = urlRequest
if let urlString = urlRequest.url?.absoluteString, urlString.hasPrefix("https://api.authenticated.com") {
///使用访问令牌设置Authorization请求头值。
urlRequest.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")
}
return urlRequest
}
}
在Alamofire中您可以轻松地和自己的SessionManager
一起使用它。
let sessionManager = SessionManager()
sessionManager.adapter = JWTAccessTokenAdapter(accessToken: "1234")
sessionManager.request("https://api.authenticated.com/get")
这就是验证外发请求所需的一切。
创建一个请求重试器
RequestRetrier
协议的工作原理也非常相似。扩展JWTAccessTokenAdapter
并要求它在获得401 Authorization Required
响应状态码时刷新令牌。
extension JWTAccessTokenAdapter: RequestRetrier {
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
guard let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 else {
completion(false, 0.0)
return
}
refreshToken { [weak self] accessToken in
guard let strongSelf = self else { return }
strongSelf.accessToken = accessToken
completion(true, 0.0)
}
}
}
在成功刷新访问令牌以便后续重试失败的请求之后,我们触发完成回调。该请求将再次触发,并使用刷新的访问令牌成功。
请求适配器的其他用法示例
请求适配器也适用于其他用例。除了使用URLProtocols打印每个外发的请求外,您也可以完美地使用请求适配器来实现。
final class PrintRequestsAdapter: RequestAdapter {
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
print("🚀 Running request: \(urlRequest.httpMethod ?? "") - \(urlRequest.url?.absoluteString ?? "")")
return urlRequest
}
}
请求适配器和自定义URLProtocol之间的区别在于,完成请求后不会获得回调。如果您想了解更多有关此内容,查看使用自定义URLProtocol打印数据。