我目前正在开发一款POC应用I have previously posted about it here。我试图处理身份验证令牌的自动刷新,如果我的服务器给我401错误(未经授权)。
这是我的演示函数,它从服务器请求一些信息(我可以故意发送它有效/无效的auth令牌)
NSInteger retryAttempts = 0;
NSInteger retryMax = 1;
- (void) requestDataForUser {
NSLog(@"requestDataForUser - Called");
//Indicate Network Activity
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = TRUE;
});
//Build request URL String
NSString *requestString = [NSString stringWithFormat:@"%@%@%@",baseURL,requestURL,@"3"];//Change to allow change in username here.
//Get auth token
NSString *accessToken = [SAMKeychain passwordForService:kServer account:kKeyAccessToken];
NSString *requestAuthorization = [NSString stringWithFormat:@"%@ %@", @"Bearer", accessToken];
//Initialize url request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
//Set the url for the request
[request setURL:[NSURL URLWithString:requestString]];
//Set HTTP method for request
[request setHTTPMethod:@"GET"];
//Set HTTP header field with the authorization token
[request setValue:requestAuthorization forHTTPHeaderField:@"Authorization"];
//Create full request
NSURLSession *session = [NSURLSession sharedSession];
__weak typeof (self) weakSelf = self;
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSLog(@"Status Code: %ld\n",(long)httpResponse.statusCode);
NSString *message = [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode];
NSLog(@"Message: %@", message);
NSLog(@"requestDataForUser - Responce from server");
//Check for an error, if there is no error we proceed.
if (!error) {
if (retryAttempts <= retryMax) {
switch (httpResponse.statusCode) {
case 200 ... 299:
NSLog(@"SUCCESS");
NSLog(@"Performing any completion related functions!");
break;
case 401:
NSLog(@"401 Challenge - Retrying Authentication, Attempt %ld", (long)retryAttempts);
[weakSelf refreshAuth];
[weakSelf requestDataForUser];//retries this function
retryAttempts += 1;
break;
}}
else {
NSLog(@"401 Error Recieved - Retried credentials %ld time(s), please check your details are correct", (long)retryMax);
retryAttempts = 0; //Reset retry counter
//Alert controller?
}
//Get que and perform any UI changes
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = FALSE;
});
}
else {
//Failed request
NSLog(@"requestDataForUser - error : %@", error.description);
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = FALSE;
});
}
}];
[dataTask resume];
}
我遇到的问题出现在请求的401挑战部分。我想要做的是请求/刷新一个新令牌(在最后一次迭代中刷新但当前我的服务器在令牌刷新时有点击中/未命中,因此我在此示例中请求新令牌)。那么让我们来看看我的服务器挑战部分:
case 401:
NSLog(@"401 Challenge - Retrying Authentication, Attempt %ld", (long)retryAttempts);
[weakSelf refreshAuth];
[weakSelf requestDataForUser];//retries this function
retryAttempts += 1;
break;
所以我在这里打印出尝试号码,我可以手动设置这个&#39;阻止&#39;重试,直到它放弃并向用户抛出错误。接下来,它将调用auth令牌,重试请求并将retryAttempts增加1。
我的问题是,当我请求一个新令牌时,我会异步执行此请求,然后发送请求然后我的函数重试(显然没有新令牌),然后它会抛出错误。然后我的令牌返回并打印到控制台,新令牌成功返回。
我看过信号量,但我似乎无法让它们工作(因为我的requestAuthToken方法没有完成块)。无论如何我可以强制auth请求同步吗?
我还试图让我的requestAuth方法返回一个BOOL并在401块中循环bool直到它变为true,但是它永远不会被设置为true而while循环会一直持续。
感谢任何和所有帮助!
答案 0 :(得分:0)
假设您可以更改requestAuth的实现,请向requestAuth函数添加完成处理程序参数。
在requestAuth实现中,在收到令牌后调用该处理程序。然后在requestDataForUser中:
cs
否则,使用NSOperationQueue并将最大并发操作设置为1:
case 401:
NSLog(@"401 Challenge - Retrying Authentication, Attempt %ld", (long)retryAttempts);
[weakSelf refreshAuth withCompletionHandler:weakself.requestDataForUser];
retryAttempts += 1;
break;