收到令牌后,当令牌结束时,如何在登录后自动调用令牌?在同一页上
Alamofire.request(urlString, method: .post, parameters: newPost, encoding: JSONEncoding.default)
.responseJSON { response in
if let json = response.result.value as? [String : Any]{
print("JSON: \(json)")
if UserDefaults.standard.bool(forKey: "logged_in") {
Token = json["Token"]! as! String
UserDefaults.standard.set(Token, forKey: "Token")
UserDefaults.standard.synchronize()
}
} else {
print("Did not receive json")
}
//expectation.fulfill()
}
答案 0 :(得分:6)
对于Authorisation Token
,理想的做法是从服务器端进行检查,请求的API调用TOKEN
是否有效。如果令牌未匹配或已过期,则会提供HTTP status code
401
,您需要先从移动端检查状态代码,如果找到401
,则需要强制注销或重新登录需要一个新令牌,您可以将其保存在UserDefaults
。
答案 1 :(得分:3)
场景1:您需要告诉后台开发人员谁做了您的网络服务,他需要检查TOKEN是否有效。如果令牌过期,他需要提供消息代码或消息“令牌已过期"并且您可以在“响应”中检查消息代码是否已过期,而不是导航“登录”屏幕。 这是最佳做法。
场景2:如果您不想从应用退出,并让应用程序继续使用新令牌自动刷新,请告诉webservice开发人员,无论何时令牌过期,他都会在响应字段中返回新令牌"授权"从代码方面来说,您需要检查每个请求是否授权包含新令牌。如果它包含,则表示您需要在userdefault中将旧令牌替换为新令牌。
以下是我在Swift3中的代码:
func requestApiCall(_ urlString: String, paramData: NSObject, completionHandler: @escaping (NSDictionary?, NSError?) -> ()) {
let token = UserDefaults.standard.object(forKey: “token” as String)
var headersVal = [
"Authorization": "Bearer "+(token as String),
]
Alamofire.request(urlString, method: .post, parameters: paramData as? [String : AnyObject],encoding: JSONEncoding.default, headers: headersVal)
.responseJSON { response in
if let authorization = response.response?.allHeaderFields["Authorization"] as? String {
var newToken : String = authorization
UserDefaults.standard.set(newToken, forKey: "token")
UserDefaults.standard.synchronize()
}
switch response.result {
case .success(let value):
if let res = response.result.value {
let response = res as! NSDictionary
let message = response.object(forKey: "message”)!
print(message)
if message as! String == "Token has been expired"
{
self.showLoginScreen()
}
}
completionHandler(value as? NSDictionary, nil)
case .failure(let error):
if error._code == -1001 {
print("timeout")
}
completionHandler(nil, nil)
}
}
}
答案 2 :(得分:0)
在令牌过期时为新令牌调用服务对您的应用程序不安全,因为如果令牌过期并且您为新令牌调用服务,则任何人都可以访问您的应用或其数据。更好的方法是注销/退出用户并要求他再次登录。
但是如果你想这样做,那么创建一个用户获取新令牌的方法,并在获得令牌过期代码后调用它。
但你需要与你的后端开发人员讨论这个新api,因此你可以进一步移动
让我知道帮助。谢谢
答案 3 :(得分:0)
我更喜欢使用Moya
框架(Alamofire下的抽象)和PromiseKit
。它可以更轻松地编写异步代码并在部件之间创建依赖关系。我包装了所有业务逻辑,用于在类中发送请求。请求的主要功能(public func register(device: String, type: String) -> Promise<Device>
)返回Promise
个对象。在recover
块中,我验证了错误代码,如果需要,我刷新令牌并重复失败的请求。代码示例如下:
public protocol HttpClientInterface {
...
func register(device: String, type: String) -> Promise<Device>
...
}
public func register(device: String, type: String) -> Promise<Device> {
return self.sendRegisterRequest(with: device, type: type)
.then {
self.parseRegister(response: $0)
}
.recover { lerror -> Promise<Device> in
guard let error = lerror as? HttpClientError,
case .server(let value) = error,
value == ServerError.notAuthenticated,
let refreshToken = self.credentialsStore.get()?.token?.refreshToken else {
throw lerror
}
return self.sendRefreshSessionRequest(operatorId: self.operatorId, refreshToken: refreshToken)
.then { data -> Promise<AuthToken> in
return self.parseRefreshSession(data)
}
.then { token -> Promise<Device> in
self.credentialsStore.update(token: token)
return self.register(device: device, type: type)
}
.catch { error in
if let myError = error as? HttpClientError,
case .server(let value) = httpError,
value == ServerError.notAuthenticated {
self.credentialsStore.accessDenied()
}
}
}
}
func sendRegisterRequest(with name: String, type: String) -> Promise<Data> {
return Promise { fulfill, reject in
self.client.request(.register(device: name, type: type)) {
self.obtain(result: $0,
successStatusCodes: [200, 201],
fulfill: fulfill,
reject: reject)
}
}
}
func parseRegister(response data: Data) -> Promise<Device> {
return Promise { fulfill, reject in
if let account = Account(data: data),
let device = account.devices?.last {
fulfill(device)
} else {
reject(HttpClientError.internalError())
}
}
}