刷新令牌的正确方法 [英] Right way to refresh the token
问题描述
RequestManager 类
中有一个函数 getUser
在我的 VC
中调用.
There is a function getUser
in RequestManager class
that called in my VC
.
func getUser(onCompletion: @escaping (_ result: User?, error: String?) -> Void) {
Alamofire.request(Router.getUser).responseJSON { (response) in
// here is the work with response
}
}
如果此请求返回 403
,则表示 access_token
已过期.我需要刷新令牌并重复来自我的 VC
的请求.
If this request returns 403
it means access_token
is expired. I need to refresh token and repeat the request from my VC
.
现在是问题.
如何以正确的方式刷新令牌并重复请求?
How to refresh token and repeat the request in the right way?
在MyViewController
或getUser
方法中处理错误和刷新令牌不是一个好主意,因为我有很多VCs
和请求方法
.
To handle the error and refresh token in MyViewController
or getUser
method is not good idea because I have a lot of VCs
and request methods
.
我需要类似的东西:VC
调用该方法并获取 User
即使令牌已过期并且 refreshToken
必须不 在所有请求方法中.
I need something like: VC
calls the method and gets the User
even if token is expired and refreshToken
must not be in all request methods.
编辑
refreshToken
方法
func refreshToken(onCompletion: @escaping (_ result: Bool?) -> Void) {
Alamofire.request(Router.refreshToken).responseJSON { (response) in
print(response)
if response.response?.statusCode == 200 {
guard let data = response.data else { return onCompletion(false) }
let token = try? JSONDecoder().decode(Token.self, from: data)
token?.setToken()
onCompletion(true)
} else {
onCompletion(false)
}
}
}
推荐答案
为了解决这个问题,我创建了一个类,我们将从中调用每个 API,比如 BaseService.swift
.
To solve this, I created a class from which we will call every API, say BaseService.swift
.
BaseService.swift :
import Foundation
import Alamofire
import iComponents
struct AlamofireRequestModal {
var method: Alamofire.HTTPMethod
var path: String
var parameters: [String: AnyObject]?
var encoding: ParameterEncoding
var headers: [String: String]?
init() {
method = .get
path = ""
parameters = nil
encoding = JSONEncoding() as ParameterEncoding
headers = ["Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
"Cache-Control": "no-cache"]
}
}
class BaseService: NSObject {
func callWebServiceAlamofire(_ alamoReq: AlamofireRequestModal, success: @escaping ((_ responseObject: AnyObject?) -> Void), failure: @escaping ((_ error: NSError?) -> Void)) {
// Create alamofire request
// "alamoReq" is overridden in services, which will create a request here
let req = Alamofire.request(alamoReq.path, method: alamoReq.method, parameters: alamoReq.parameters, encoding: alamoReq.encoding, headers: alamoReq.headers)
// Call response handler method of alamofire
req.validate(statusCode: 200..<600).responseJSON(completionHandler: { response in
let statusCode = response.response?.statusCode
switch response.result {
case .success(let data):
if statusCode == 200 {
Logs.DLog(object: "\n Success: \(response)")
success(data as AnyObject?)
} else if statusCode == 403 {
// Access token expire
self.requestForGetNewAccessToken(alaomReq: alamoReq, success: success, failure: failure)
} else {
let errorDict: [String: Any] = ((data as? NSDictionary)! as? [String: Any])!
Logs.DLog(object: "\n \(errorDict)")
failure(errorTemp as NSError?)
}
case .failure(let error):
Logs.DLog(object: "\n Failure: \(error.localizedDescription)")
failure(error as NSError?)
}
})
}
}
extension BaseService {
func getAccessToken() -> String {
if let accessToken = UserDefaults.standard.value(forKey: UserDefault.userAccessToken) as? String {
return "Bearer " + accessToken
} else {
return ""
}
}
// MARK: - API CALL
func requestForGetNewAccessToken(alaomReq: AlamofireRequestModal, success: @escaping ((_ responseObject: AnyObject?) -> Void), failure: @escaping ((_ error: NSError?) -> Void) ) {
UserModal().getAccessToken(success: { (responseObj) in
if let accessToken = responseObj?.value(forKey: "accessToken") {
UserDefaults.standard.set(accessToken, forKey: UserDefault.userAccessToken)
}
// override existing alaomReq (updating token in header)
var request: AlamofireRequestModal = alaomReq
request.headers = ["Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
"Cache-Control": "no-cache",
"X-Authorization": self.getAccessToken()]
self.callWebServiceAlamofire(request, success: success, failure: failure)
}, failure: { (_) in
self.requestForGetNewAccessToken(alaomReq: alaomReq, success: success, failure: failure)
})
}
}
为了从此调用调用 API,我们需要创建一个 AlamofireRequestModal
对象并用必要的参数覆盖它.
For calling the API from this call, we need to create a object of AlamofireRequestModal
and override it with necessary parameter.
例如,我创建了一个文件 APIService.swift
,其中我们有一个用于 getUserProfileData
的方法.
For example I created a file APIService.swift
in which we have a method for getUserProfileData
.
APIService.swift :
import Foundation
let GET_USER_PROFILE_METHOD = "user/profile"
struct BaseURL {
// Local Server
static let urlString: String = "http://192.168.10.236: 8084/"
// QAT Server
// static let urlString: String = "http://192.171.286.74: 8080/"
static let staging: String = BaseURL.urlString + "api/v1/"
}
class APIService: BaseService {
func getUserProfile(success: @escaping ((_ responseObject: AnyObject?) -> Void), failure: @escaping ((_ error: NSError?) -> Void)) {
var request: AlamofireRequestModal = AlamofireRequestModal()
request.method = .get
request.path = BaseURL.staging + GET_USER_PROFILE_METHOD
request.headers = ["Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
"Cache-Control": "no-cache",
"X-Authorization": getAccessToken()]
self.callWebServiceAlamofire(request, success: success, failure: failure)
}
}
说明:
在代码块中:
else if statusCode == 403 {
// Access token expire
self.requestForGetNewAccessToken(alaomReq: alamoReq, success: success, failure: failure)
}
我调用 getNewAccessToken API(在您的情况下是刷新令牌),请求(它可以是基于 APIService.swift 的任何请求).
I call getNewAccessToken API (say refresh-token, in your case), with the request( it could be any request based from APIService.swift).
当我们获得新令牌时,我将其保存为用户默认值,然后我将更新请求(我在刷新令牌 API 调用中作为参数获取的请求),并将按原样传递成功和失败块.
When we get new token I save it user-defaults then I will update the request( the one I am getting as a parameter in refresh-token API call), and will pass the success and failure block as it is.
这篇关于刷新令牌的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!