我正在将iOS应用程序从NSURLConnection转换为NSURLSession。'didReceiveChallenge'在调用ServerTrust之后不会调用HttpBasic身份验证
服务器与同时使用https(由已识别的CA签名的证书)和基本验证进行交互。
而不是使用完成块的数据返回,我使用自定义代表。我在其他地方看到过,使用自定义代表意味着我应该对AuthenticationChallenges做出响应,而不是依赖于CredentialStorage(不是那也适用,但那是另一个问题)。
我的问题是,对于ServerTrust而言,发生一次挑战,但不会再次为HttpBasic身份验证调用。所以,我的会议超时。
我已经尝试使用完成块为'defaultSession dataTaskWithRequest'而不是自定义的代表,只是为了看看我能否通过这一点,但它没有区别。我也尝试使用CredentialStorage作为HttpBasic凭证,但如上所述,没有喜悦。
这让我难住了。有任何想法吗?
(void)URLSession:(NSURLSession *)connection
// task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: Using SSL");
#endif // DEBUG
if ([challenge.protectionSpace.host isEqualToString:HOST])
{
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: Using Protection Space Host - %@", HOST);
#endif // DEBUG
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
else
{
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}
else
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic] ||
[challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPDigest])
{
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: (Basic/Digest) #%ld - user: %@, password: %@",
(long)[challenge previousFailureCount], USERNAME, PASSWORD);
#endif // DEBUG
if ([challenge previousFailureCount] == 0)
{
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: previousFailureCount == 0");
#endif // DEBUG
NSURLCredential *newCredential;
newCredential = [NSURLCredential credentialWithUser:USERNAME
password:PASSWORD
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}
else
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
// inform the user that the user name and password
// in the preferences are incorrect
#if 1 && defined(DEBUG)
NSLog (@"didReceiveChallenge: Failed Authentication");
#endif // DEBUG
// ...error will be handled by connection didFailWithError
}
}
#ifdef DEBUG
else
{
NSLog(@"didReceiveChallenge: Not handled!");
}
#endif // DEBUG
}
感谢您的回复,感谢您花时间回复。我的应用程序只能对我自己的服务器说话,所以至少现在我只关心验证该保护空间的证书。对于其他挑战类型,我正在处理(并期待)一个永远不会到来的HTTPBasic。如果我有其他人没有处理,我会得到一个诊断,但我不知道。再次感谢。 – Snips
对不起,我第一次看到这个时没有注意到第四个问题。您正在对挑战发件人调用方法,这是*不是用NSURLSession做的事情的有效方法。您*必须*通过选择的处置方式和可选的凭证来调用完成方法。否则,您的请求将全部等待您的代码调用完成。 – dgatwood