[编辑提供更多信息]
(我没有使用AFNetworking进行这个项目,我可能会在将来这样做,但是首先要解决这个问题/误会)
服务器设置
我无法在这里提供真正的服务,但它是一种简单可靠的服务,可以根据以下URL传回XML:
https://username:password@example.com/webservice
我想使用GET通过HTTPS连接到URL,并确定任何身份验证失败(http状态代码401).
我已经确认Web服务可用,并且可以成功(http状态码200)使用指定的用户名和密码从URL获取XML.我已经通过网络浏览器和AFNetworking 2.0.3和使用NSURLConnection完成了这一点.
我也确认我正在各个阶段使用正确的证书.
给出正确的凭据和以下代码:
- // Note: NO delegate provided here.
- self.sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
- self.session = [NSURLSession sessionWithConfiguration:self.sessionConfig
- delegate:nil
- delegateQueue:nil];
- NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:self.requestURL completionHandler: ...
上面的代码将工作.它将成功连接到服务器,获取http状态码为200,并返回(XML)数据.
问题1
在凭据无效的情况下,这种简单的方法失败.在这种情况下,完成块从不被调用,不提供状态码(401),最终任务超时.
试验解决方案
我分配了一个代表到NSURLSession,并处理以下回调:
- -(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,NSURLCredential *credential))completionHandler
- {
- if (_sessionFailureCount == 0) {
- NSURLCredential *cred = [NSURLCredential credentialWithUser:self.userName password:self.password persistence:NSURLCredentialPersistenceNone];
- completionHandler(NSURLSessionAuthChallengeUseCredential,cred);
- } else {
- completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,nil);
- }
- _sessionFailureCount++;
- }
- - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
- didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
- completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,NSURLCredential *credential))completionHandler
- {
- if (_taskFailureCount == 0) {
- NSURLCredential *cred = [NSURLCredential credentialWithUser:self.userName password:self.password persistence:NSURLCredentialPersistenceNone];
- completionHandler(NSURLSessionAuthChallengeUseCredential,nil);
- }
- _taskFailureCount++;
- }
问题1使用试验溶液时
请注意使用ivars _sessionFailureCount和_taskFailureCount.我正在使用这些,因为挑战对象的@prevIoUsFailureCount属性从不提前!它始终保持为零,无论这些回调方法被调用多少次.
问题2使用试验溶液时
尽管使用正确的凭据(通过成功使用无代理证明证明),认证失败.
发生以下回调:
- URLSession:didReceiveChallenge:completionHandler:
- (challenge @ prevIoUsFailureCount reports as zero)
- (_sessionFailureCount reports as zero)
- (completion handler is called with correct credentials)
- (there is no challenge @error provided)
- (there is no challenge @failureResponse provided)
- URLSession:didReceiveChallenge:completionHandler:
- (challenge @ prevIoUsFailureCount reports as **zero**!!)
- (_sessionFailureCount reports as one)
- (completion handler is called with request to cancel challenge)
- (there is no challenge @error provided)
- (there is no challenge @failureResponse provided)
- // Finally,the Data Task's completion handler is then called on us.
- (the http status code is reported as zero)
- (the NSError is reported as NSURLErrorDomain Code=-999 "cancelled")
(NSError还提供了一个NSErrorFailingURLKey,它显示了URL和凭据是正确的.)
欢迎任何建议!
解决方法
您不需要为此执行代理方法,只需在请求上设置授权HTTP头,例如.
- NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://whatever.com"]];
- NSString *authStr = @"username:password";
- NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
- NSString *authValue = [NSString stringWithFormat: @"Basic %@",[authData base64EncodedStringWithOptions:0]];
- [request setValue:authValue forHTTPHeaderField:@"Authorization"];
- //create the task
- NSURLSessionDataTask* task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data,NSURLResponse *response,NSError *error) {
- }];