当我刷新令牌时,我从后端获得一个expires_in
Int。
我需要存储令牌到期的日期,并在调用API之前检查它。
所以我的模型是这样的:
struct TokenModel: Codable {
var access_token: String
var refresh_token: String
var token_type: String
var expires_in: Int
var scope: String
var expires: Date? {
let now = Date()
let calendar = Calendar.current
return calendar.date(byAdding: .second, value: expires_in, to: now)
}
}
然后根据当前日期检查expires
。
让我担心的是日历参数。 用户是否可以更改设备或日历上的日期/时间,然后逻辑将不工作?
我想转换为ISO8601formatter
,但似乎无法轻松转换到目前为止。。。
这里有个缺陷。 expires
不返回真正的截止日期。 它现在总是返回+expires_in
秒。 那个日期永远在未来。
一种可能的解决方法是标记实例的创建时间。
struct TokenModel: Codable {
var access_token: String
var refresh_token: String
var token_type: String
var expires_in: Int
var scope: String
let startingDate = Date()
var expires: Date? {
let calendar = Calendar.current
return calendar.date(byAdding: .second, value: expires_in, to: startingDate)
}
}
这也有问题。 不小心处理TokenModel
实例可能会导致其他缺陷。
如果服务器提供了过期时间,那么您可能会遇到时间漂移的问题。 如果服务器关闭了几秒,或者如果客户端从标准时间关闭了几秒,那么过期时间就关闭了。
我用过几次的解决方案是把责任分开。 创建单独的授权管理器。
struct TokenModel: Codable {
let access_token: String
let refresh_token: String
let token_type: String
let expires_in: Int
let scope: String
}
class AuthorizationManager {
var accessToken: String?
var refreshToken: String?
var tokenType: String?
var expiration: Date?
var scope: String?
lazy var calendar: Calendar = .current
func update(token: TokenModel) {
if let tokenExpiration = calendar.date(byAdding: .second, value: token.expires_in, to: Date()) {
accessToken = token.access_token
refreshToken = token.refresh_token
tokenType = token.token_type
expiration = tokenExpiration
scope = token.scope
}
}
}