AWS API 网关刷新不可靠
AWS API Gateway unreliability in refresh
我使用 API 网关有一段时间了,我只是稍微更改了 api 以允许另一个功能。我进入 api 网关并测试了该功能以确保其正常工作。然后我在 iPhone 上试了一下,效果也不错。后来随机地,我开始收到 {errorMessage: "Task timed out after 3.00 seconds"} 的重复实例。我不明白为什么一个简单的登录方法(API Gateway 中的方法)会超时,特别是因为我在 iPhone(之前工作时)和直接使用api 网关控制台。
评论:我没有使用生成的 sdk 或 AWSAPIGatewayClient。我只是在发出一个 http 请求。
http 请求登录
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *post = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
[defaults objectForKey:@"username"], @"username",
[defaults objectForKey:@"password"], @"password",
nil];
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:post options:0 error:&error];
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"someLoginEndpoint"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *newJSON = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&error];
if(!newJSON || [newJSON objectForKey:@"errorMessage"]){
NSLog(@"%@",newJSON);
callBack(false);
NSLog(@"DID NOT AUTHENTICATE");
}else{
NSLog(@"%@",newJSON);
[defaults setValue:[newJSON objectForKey:@"Token"] forKey:@"Token"];
[defaults setValue:[newJSON objectForKey:@"IdentityId"] forKey:@"IdentityId"];
[self authenticateUser:^(BOOL call){
callBack(call);
}];
}
}] resume];
刷新方式
- (AWSTask *)refresh {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![self authenticatedWithProvider]) {
return [super getIdentityId];
}else{
NSDictionary *post = [[NSDictionary alloc] initWithObjectsAndKeys:
[defaults objectForKey:@"username"], @"username",
[defaults objectForKey:@"password"], @"password",
nil];
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:post options:0 error:&error];
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"someLoginEndpoint"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
__block BOOL isLogged = false;
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *newJSON = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&error];
isLogged = true;
if(!newJSON){
NSLog(@"DID NOT AUTHENTICATE");
}else{
NSLog(@"The IdentityID in the refresh method: %@",[newJSON objectForKey:@"IdentityId" ]);
NSLog(@"The token in the refresh method: %@",[newJSON objectForKey:@"Token" ]);
self.identityId = [newJSON objectForKey:@"IdentityId" ];
self.token = [newJSON objectForKey:@"Token" ];
}
}] resume];
return [super getIdentityId];
}
return [super getIdentityId];
}
验证用户
//BusytimeAuthenticated
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
id<AWSCognitoIdentityProvider> identityProvider = [[BusytimeAuthenticated alloc] initWithRegionType:AWSRegionUSEast1
identityId:nil
identityPoolId:@"somePoolID"
logins:@{@"cognito-identity.amazonaws.com": [defaults objectForKey:@"Token"]}
providerName:@"cognito-identity.amazonaws.com"
];
credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1
identityProvider:identityProvider
unauthRoleArn:nil
authRoleArn:nil];
configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1
credentialsProvider:self.credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
[[credentialsProvider refresh] continueWithBlock:^id(AWSTask *task){
callBack(true);
return nil;
}];
}
错误
无法刷新。错误是 [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=10 "(null)" UserInfo={message=Invalid login token。无法传入 Cognito 令牌。,__type=NotAuthorizedException}]
我的基本问题是,为什么这个操作如此不可靠?它偶尔可以登录我的用户,然后当我使用刷新方法时,我传递了相同的凭据,但并排请求导致第二个请求失败。
关于超时:
如评论中所述,Lambda 冷启动可能会导致您的 API 网关调用超时,您可能需要优化 Lambda 以避免超时。
关于刷新错误:
您正在登录映射中使用 cognito-identity.amazonaws.com,但使用 IdentityProvider 模式进行刷新。这就是第一次身份验证成功但尝试刷新失败的原因。刷新中的逻辑永远不会触发。
我建议您查看我们的 end-to-end sample 以了解处理开发人员身份验证的建议流程。
如果您想继续在登录映射中使用 cognito-identity.amazonaws.com,那么您的令牌刷新实际上需要在 外部处理identity/credentials 提供商的 ,类似于您处理 Facebook 令牌的方式。
我使用 API 网关有一段时间了,我只是稍微更改了 api 以允许另一个功能。我进入 api 网关并测试了该功能以确保其正常工作。然后我在 iPhone 上试了一下,效果也不错。后来随机地,我开始收到 {errorMessage: "Task timed out after 3.00 seconds"} 的重复实例。我不明白为什么一个简单的登录方法(API Gateway 中的方法)会超时,特别是因为我在 iPhone(之前工作时)和直接使用api 网关控制台。
评论:我没有使用生成的 sdk 或 AWSAPIGatewayClient。我只是在发出一个 http 请求。
http 请求登录
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *post = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
[defaults objectForKey:@"username"], @"username",
[defaults objectForKey:@"password"], @"password",
nil];
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:post options:0 error:&error];
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"someLoginEndpoint"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *newJSON = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&error];
if(!newJSON || [newJSON objectForKey:@"errorMessage"]){
NSLog(@"%@",newJSON);
callBack(false);
NSLog(@"DID NOT AUTHENTICATE");
}else{
NSLog(@"%@",newJSON);
[defaults setValue:[newJSON objectForKey:@"Token"] forKey:@"Token"];
[defaults setValue:[newJSON objectForKey:@"IdentityId"] forKey:@"IdentityId"];
[self authenticateUser:^(BOOL call){
callBack(call);
}];
}
}] resume];
刷新方式
- (AWSTask *)refresh {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![self authenticatedWithProvider]) {
return [super getIdentityId];
}else{
NSDictionary *post = [[NSDictionary alloc] initWithObjectsAndKeys:
[defaults objectForKey:@"username"], @"username",
[defaults objectForKey:@"password"], @"password",
nil];
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:post options:0 error:&error];
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"someLoginEndpoint"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
__block BOOL isLogged = false;
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *newJSON = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&error];
isLogged = true;
if(!newJSON){
NSLog(@"DID NOT AUTHENTICATE");
}else{
NSLog(@"The IdentityID in the refresh method: %@",[newJSON objectForKey:@"IdentityId" ]);
NSLog(@"The token in the refresh method: %@",[newJSON objectForKey:@"Token" ]);
self.identityId = [newJSON objectForKey:@"IdentityId" ];
self.token = [newJSON objectForKey:@"Token" ];
}
}] resume];
return [super getIdentityId];
}
return [super getIdentityId];
}
验证用户
//BusytimeAuthenticated
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
id<AWSCognitoIdentityProvider> identityProvider = [[BusytimeAuthenticated alloc] initWithRegionType:AWSRegionUSEast1
identityId:nil
identityPoolId:@"somePoolID"
logins:@{@"cognito-identity.amazonaws.com": [defaults objectForKey:@"Token"]}
providerName:@"cognito-identity.amazonaws.com"
];
credentialsProvider = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1
identityProvider:identityProvider
unauthRoleArn:nil
authRoleArn:nil];
configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1
credentialsProvider:self.credentialsProvider];
AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
[[credentialsProvider refresh] continueWithBlock:^id(AWSTask *task){
callBack(true);
return nil;
}];
}
错误 无法刷新。错误是 [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=10 "(null)" UserInfo={message=Invalid login token。无法传入 Cognito 令牌。,__type=NotAuthorizedException}]
我的基本问题是,为什么这个操作如此不可靠?它偶尔可以登录我的用户,然后当我使用刷新方法时,我传递了相同的凭据,但并排请求导致第二个请求失败。
关于超时:
如评论中所述,Lambda 冷启动可能会导致您的 API 网关调用超时,您可能需要优化 Lambda 以避免超时。
关于刷新错误:
您正在登录映射中使用 cognito-identity.amazonaws.com,但使用 IdentityProvider 模式进行刷新。这就是第一次身份验证成功但尝试刷新失败的原因。刷新中的逻辑永远不会触发。
我建议您查看我们的 end-to-end sample 以了解处理开发人员身份验证的建议流程。
如果您想继续在登录映射中使用 cognito-identity.amazonaws.com,那么您的令牌刷新实际上需要在 外部处理identity/credentials 提供商的 ,类似于您处理 Facebook 令牌的方式。