首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Moya刷新auth标记

使用Moya刷新auth标记
EN

Stack Overflow用户
提问于 2019-03-01 07:57:38
回答 1查看 4.1K关注 0票数 7

我正在使用Moya与我的API进行通信。对于我的许多端点,我要求对用户进行身份验证(即,持有者令牌基于Authorization标头)。

在Moya文档here中,我发现了如何包含Authorization头以及持有者令牌。

但是,我现在需要实现auth令牌刷新,但我不确定如何做到这一点。

我在Moya的Github上找到了this thread的答案,看起来可能会有帮助,但我不知道把代码放在哪里。下面是答案的代码:

代码语言:javascript
运行
复制
// (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提供者提供的类:

代码语言:javascript
运行
复制
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)!
    }
}

我应该在我的代码中把答案的代码放在哪里呢?我是不是遗漏了什么?

EN

回答 1

Stack Overflow用户

发布于 2019-04-15 01:20:40

实际上,这个例子有点老了。所以这里有一个新的方法:

代码语言:javascript
运行
复制
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
                }
            }
    }
}

用法:

代码语言:javascript
运行
复制
public var provider: MoyaProvider<SomeTargetType> = MoyaProvider(handleRefreshToken: true)

provider.request(...)
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54936080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档