使用 Moya 刷新身份验证令牌
Posted
技术标签:
【中文标题】使用 Moya 刷新身份验证令牌【英文标题】:Refreshing auth token with Moya 【发布时间】:2019-02-28 23:57:37 【问题描述】:我正在使用 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)!
我应该将答案的代码放在我的代码中的什么位置?我错过了什么吗?
【问题讨论】:
【参考方案1】:实际上,这个例子有点老了。所以这是一个新的:
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(...)
【讨论】:
authenticationProvider.request
实例来自哪里?
如果发出多个请求会怎样?每次请求都会多次调用refreshToken api吗?
@ugur 您应该检查令牌是否已过期,然后再进行刷新,如答案中所述
好的,但假设令牌已过期并且同时发出请求。因此,在这种情况下,将为每个请求触发刷新令牌,并且假设每个刷新令牌都使前一个刷新令牌过期,实际请求可能会使用错误的令牌恢复。 Alamofire RequestRetrier 通过在列表中收集请求并在刷新令牌响应后恢复所有请求来解决此问题。我是 Moya 的新手,我错过了什么吗?
@session过期如何使用?以上是关于使用 Moya 刷新身份验证令牌的主要内容,如果未能解决你的问题,请参考以下文章