我正在使用Moya与我的API进行通信。对于我的许多端点,我要求对用户进行身份验证(即,持有者令牌基于Authorization标头)。
在Moya文档here中,我发现了如何包含Authorization头以及持有者令牌。
但是,我现在需要实现auth令牌刷新,但我不确定如何做到这一点。
我在Moya的Github上找到了this thread的答案,看起来可能会有帮助,但我不知道把代码放在哪里。下面是答案的代码:
// (Endpoint<Target>, NSURLRequest -> Void) -> Void
static func endpointResolver<T>() -> MoyaProvider<T>.RequestClosure where T: TargetType {
return { (endpoint, closure) in
let request = endpoint.urlRequest!
request.httpShouldHandleCookies = false
if (tokenIsOK) {
// Token is valid, so just resume the request and let AccessTokenPlugin set the Authentication header
closure(.success(request))
return
}
// authenticationProvider is a MoyaProvider<Authentication> for example
authenticationProvider.request(.refreshToken(params)) { result in
switch result {
case .success(let response):
self.token = response.mapJSON()["token"]
closure(.success(request)) // This line will "resume" the actual request, and then you can use AccessTokenPlugin to set the Authentication header
case .failure(let error):
closure(.failure(error)) //something went terrible wrong! Request will not be performed
}
}
}
}
这是我为我的Moya提供者提供的类:
import Foundation
import Moya
enum ApiService {
case signIn(email: String, password: String)
case like(id: Int, type: String)
}
extension ApiService: TargetType, AccessTokenAuthorizable {
var authorizationType: AuthorizationType {
switch self {
case .signIn(_, _):
return .basic
case .like(_, _):
return .bearer
}
}
var baseURL: URL {
return URL(string: Constants.apiUrl)!
}
var path: String {
switch self {
case .signIn(_, _):
return "user/signin"
case .like(_, _):
return "message/like"
}
}
var method: Moya.Method {
switch self {
case .signIn, .like:
return .post
}
}
var task: Task {
switch self {
case let .signIn(email, password):
return .requestParameters(parameters: ["email": email, "password": password], encoding: JSONEncoding.default)
case let .like(id, type):
return .requestParameters(parameters: ["messageId": id, "type": type], encoding: JSONEncoding.default)
}
}
var sampleData: Data {
return Data()
}
var headers: [String: String]? {
return ["Content-type": "application/json"]
}
}
private extension String {
var urlEscaped: String {
return addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
}
var utf8Encoded: Data {
return data(using: .utf8)!
}
}
我应该在我的代码中把答案的代码放在哪里呢?我是不是遗漏了什么?
发布于 2019-04-15 01:20:40
实际上,这个例子有点老了。所以这里有一个新的方法:
extension MoyaProvider {
convenience init(handleRefreshToken: Bool) {
if handleRefreshToken {
self.init(requestClosure: MoyaProvider.endpointResolver())
} else {
self.init()
}
}
static func endpointResolver() -> MoyaProvider<Target>.RequestClosure {
return { (endpoint, closure) in
//Getting the original request
let request = try! endpoint.urlRequest()
//assume you have saved the existing token somewhere
if (#tokenIsNotExpired#) {
// Token is valid, so just resume the original request
closure(.success(request))
return
}
//Do a request to refresh the authtoken based on refreshToken
authenticationProvider.request(.refreshToken(params)) { result in
switch result {
case .success(let response):
let token = response.mapJSON()["token"]
let newRefreshToken = response.mapJSON()["refreshToken"]
//overwrite your old token with the new token
//overwrite your old refreshToken with the new refresh token
closure(.success(request)) // This line will "resume" the actual request, and then you can use AccessTokenPlugin to set the Authentication header
case .failure(let error):
closure(.failure(error)) //something went terrible wrong! Request will not be performed
}
}
}
}
用法:
public var provider: MoyaProvider<SomeTargetType> = MoyaProvider(handleRefreshToken: true)
provider.request(...)
https://stackoverflow.com/questions/54936080
复制相似问题