文档显示了如何制作目标需要承载令牌,我这样做了
extension MyService: AccessTokenAuthorizable {
var authorizationType: AuthorizationType {
switch self {
case .resetPassword, .postTextBook, .bookmarkBook, .getBookmarks, .logout, .verify:
return .bearer
default:
return .none
}
}
}
然后它显示了如何向提供者添加令牌,我这样做
let token = "abc123"
let authPlugin = AccessTokenPlugin(tokenClosure: token)
let provider = MoyaProvider<MyService>(plugins: [authPlugin])
但是当令牌过期时,我该如何更改令牌?并且Moya是否提供了一种自动执行此过程的方法,如果我收到禁止的http响应(意味着我未获得授权),它会自动请求令牌?
答案 0 :(得分:2)
对于每个API,身份验证/授权的实现细节可能完全不同。这就是Moya
无法为您处理身份验证的原因。
也就是说,实现您自己的身份验证/授权可以通过许多方式完成。这取决于您的约束和/或偏好。截至今天,您可以在Moya documentation中找到一些稀疏概述的解决方案:
PluginType
将您的身份验证添加到请求中。但是,如果需要,可以考虑使用它来刷新令牌。您可能还需要拦截请求的完成以检测授权错误并应用您的首选恢复方案(例如,刷新令牌并重试呼叫)。endpointClosure
和/或requestClosure
。Alamofire
的{{1}}和RequestAdapter
。根据您的需要,这可以使重试更容易。但是,对他们而言,您无法直接访问RequestRetrier
,因此您可能需要找到一种方法来识别所需的不同身份验证方法(即您的TargetType
或bearer
)。 直接引用他们的文档:
此外,我强烈建议任何人从Eilodon's Networking
source code学习/获取灵感。
答案 1 :(得分:0)
我使用此更改/刷新令牌
static func send(request: TargetType) -> PrimitiveSequence<SingleTrait, Response> {
return provider.rx.request(request)
.retry(1)
.observeOn(ConcurrentDispatchQueueScheduler.init(qos: .default))
.filterSuccessfulStatusAndRedirectCodes()
.retryWhen({ (errorObservable: Observable<Error>) in
errorObservable.flatMap({ (error) -> Single<String> in
if let moyaError: MoyaError = error as? MoyaError, let response: Response = moyaError.response {
if **check forbidden http responses here** {
return provider.rx.request(.refreshToken(*your refresh token here*))
.filterSuccessfulStatusCodes()
.mapString(atKeyPath: "*json path to new access token*")
.catchError { (_) in
logout()
throw error
}
.flatMap({ (newAccessToken) -> PrimitiveSequence<SingleTrait, String> in
changeAccessToken()
return Single.just(newAccessToken)
})
}
}
throw error
})
})
}
static func logout() {
// logout action
}
static func changeAccessToken() {
// set new access token
}