我使用AWS作为开发人员身份验证身份的后端构建iOS(Swift)应用程序。一切正常,直到我关闭应用程序,保留一段时间,然后重新启动。在这种情况下,我经常(但并非总是)在尝试从AWS检索数据时收到ExpiredTokenException错误。
这是我的代码:
class DeveloperAuthenticatedIdentityProvider: AWSAbstractCognitoIdentityProvider {
var _token: String!
var _logins: [ NSObject : AnyObject ]!
override var token: String {
get {
return _token
}
}
override var logins: [ NSObject : AnyObject ]! {
get {
return _logins
}
set {
_logins = newValue
}
}
override func getIdentityId() -> AWSTask! {
if self.identityId != nil {
return AWSTask(result: self.identityId)
} else {
return AWSTask(result: nil).continueWithBlock({ (task) -> AnyObject! in
if self.identityId == nil {
return self.refresh()
}
return AWSTask(result: self.identityId)
})
}
}
override func refresh() -> AWSTask! {
let apiUrl = "https://url-goes-here" // call my server to retrieve an OpenIdToken
request.GET(apiUrl, parameters: nil, progress: nil,
success: {
(task: NSURLSessionDataTask, response: AnyObject?) -> Void in
let tmp = NSMutableDictionary()
tmp.setObject("temp", forKey: "ExampleApp")
self.logins = tmp as [ NSObject : AnyObject ]
let jsonDictionary = response as! NSDictionary
self.identityId = jsonDictionary["identityId"] as! String
self._token = jsonDictionary["token"] as! String
awstask.setResult(response)
},
failure: {
(task: NSURLSessionDataTask?, error: NSError) -> Void in
awstask.setError(error)
}
)
return awstask.task
}
}
在AppDelegate中:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let identityProvider = DeveloperAuthenticatedIdentityProvider()
// set default service configuration
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: cognitoRegion, identityProvider: identityProvider, unauthRoleArn: unauthRole, authRoleArn: authRole)
let configuration = AWSServiceConfiguration(region: defaultServiceRegion, credentialsProvider: credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
// set service configuration for S3 (my bucket is located in a different region to my Cognito and Lambda service)
let credentialsProviderForS3 = AWSCognitoCredentialsProvider(regionType: cognitoRegion, identityProvider: identityProvider, unauthRoleArn: unauthRole, authRoleArn: unauthRole)
let awsConfigurationForS3 = AWSServiceConfiguration(region: s3ServiceRegion, credentialsProvider: credentialsProviderForS3)
AWSS3TransferUtility.registerS3TransferUtilityWithConfiguration(awsConfigurationForS3, forKey: "S3")
return true
}
此post表示Cognito令牌已过期,由开发人员手动刷新。这似乎过于复杂,因为它需要设置定时刷新定时器,处理应用程序关闭和重新启动以及处理刷新过程中发生的AWS请求。有更简单的方法吗?例如,是否可以让AWS SDK在尝试使用过期令牌查询服务器时自动调用刷新?
任何帮助将不胜感激。我使用的是适用于iOS的AWS SDK的2.3.5版。
答案 0 :(得分:1)
AWS Mobile SDK for iOS 2.4.x有一个名为AWSIdentityProviderManager
的新协议。它有以下方法:
/**
* Each entry in logins represents a single login with an identity provider.
* The key is the domain of the login provider (e.g. 'graph.facebook.com') and the value is the
* OAuth/OpenId Connect token that results from an authentication with that login provider.
*/
- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins;
符合此协议的对象的责任是在请求时返回有效的logins
字典。由于此方法是异步的,因此如果缓存的令牌已过期,则可以在其中进行网络调用。实现取决于您,但在许多情况下,AWSIdentityProviderManager
管理多个AWSIdentityProvider
,聚合它们并返回logins
字典。
答案 1 :(得分:0)
不幸的是,开发人员刷新令牌是唯一的方法。
我同意,如果AWS SDK处理了这个问题,对于应用程序开发人员会更简单,但CrdentialsProvider的设计方式应该是所有提供程序的通用方式。例如,如果有人想使用Facebook作为提供者,则AWS SDK将无法自行处理刷新,开发人员将无法在其应用中处理该问题。保持SDK的刷新流程使我们能够保持CredentialsProvider的通用性。