0

该文档显示了如何使目标需要不记名令牌,我喜欢这样做

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 响应(意味着我没有被授权),它会自动请求一个令牌?

4

2 回答 2

2

对于每个 API,身份验证/授权的实现细节可能完全不同。这就是为什么Moya不会为您处理身份验证的原因。

也就是说,可以通过多种方式实现您自己的身份验证/授权。这将取决于您的限制和/或偏好。到今天为止,您可以在Moya 文档中找到一些简要概述的解决方案:

  • 使用PluginType将您的身份验证添加到请求中。但是认为如果需要,这可能会用于刷新令牌。您可能还需要拦截请求的完成以检测授权错误并应用您首选的恢复方案(例如,刷新令牌并重试调用)。
  • 同样可以使用endpointClosureand/or来实现requestClosure
  • 您还可以考虑实施Alamofire'sRequestAdapterRequestRetrier. 根据您的需要,这可以使重试更容易。但是,在它们上,您将无法直接访问您的TargetType,因此您可能需要找到一种方法来识别所需的不同身份验证方法(即您的bearernone)。

一些对其文档的直接引用:

另外,我强烈鼓励任何人从Eilodon 的Networking源代码中学习/获得灵感。

于 2018-02-09T19:46:19.000 回答
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
}
于 2018-09-02T07:20:14.470 回答