我正在使用Moya与我的API通信。对于我的许多端点,我都要求对用户进行身份验证(即,承载令牌位于Authorization标头中)。
在Moya文档here中,我发现了如何包括授权标头以及承载令牌。
但是,我现在需要实现身份验证令牌刷新,而且我不确定该怎么做。
我在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)!
}
}
我将答案的代码放在哪里?我想念什么吗?
答案 0 :(得分:0)
实际上,该示例有些陈旧。所以这是一个新的:
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(withRefreshToken: true)
provider.request(...)