使用Alamofire中的Adapter和Retrier进行身份验证

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打印数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值