iOS / Cocoa – NSURLSession – 处理基本的HTTPS授权

前端之家收集整理的这篇文章主要介绍了iOS / Cocoa – NSURLSession – 处理基本的HTTPS授权前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
[编辑提供更多信息]

(我没有使用AFNetworking进行这个项目,我可能会在将来这样做,但是首先要解决这个问题/误会)

服务器设置

我无法在这里提供真正的服务,但它是一种简单可靠的服务,可以根据以下URL传回XML

https://username:password@example.com/webservice

我想使用GET通过HTTPS连接到URL,并确定任何身份验证失败(http状态代码401).

我已经确认Web服务可用,并且可以成功(http状态码200)使用指定的用户名和密码从URL获取XML.我已经通过网络浏览器和AFNetworking 2.0.3和使用NSURLConnection完成了这一点.

我也确认我正在各个阶段使用正确的证书.

给出正确的凭据和以下代码

  1. // Note: NO delegate provided here.
  2. self.sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
  3. self.session = [NSURLSession sessionWithConfiguration:self.sessionConfig
  4. delegate:nil
  5. delegateQueue:nil];
  6.  
  7. NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:self.requestURL completionHandler: ...

上面的代码将工作.它将成功连接到服务器,获取http状态码为200,并返回(XML)数据.

问题1

在凭据无效的情况下,这种简单的方法失败.在这种情况下,完成块从不被调用,不提供状态码(401),最终任务超时.

试验解决方

我分配了一个代表到NSURLSession,并处理以下回调:

  1. -(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,NSURLCredential *credential))completionHandler
  2. {
  3. if (_sessionFailureCount == 0) {
  4. NSURLCredential *cred = [NSURLCredential credentialWithUser:self.userName password:self.password persistence:NSURLCredentialPersistenceNone];
  5. completionHandler(NSURLSessionAuthChallengeUseCredential,cred);
  6. } else {
  7. completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,nil);
  8. }
  9. _sessionFailureCount++;
  10. }
  11.  
  12. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
  13. didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
  14. completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,NSURLCredential *credential))completionHandler
  15. {
  16. if (_taskFailureCount == 0) {
  17. NSURLCredential *cred = [NSURLCredential credentialWithUser:self.userName password:self.password persistence:NSURLCredentialPersistenceNone];
  18. completionHandler(NSURLSessionAuthChallengeUseCredential,nil);
  19. }
  20. _taskFailureCount++;
  21. }

问题1使用试验溶液时

请注意使用ivars _sessionFailureCount和_taskFailureCount.我正在使用这些,因为挑战对象的@prevIoUsFailureCount属性从不提前!它始终保持为零,无论这些回调方法调用多少次.

问题2使用试验溶液时

尽管使用正确的凭据(通过成功使用无代理证明证明),认证失败.

发生以下回调:

  1. URLSession:didReceiveChallenge:completionHandler:
  2. (challenge @ prevIoUsFailureCount reports as zero)
  3. (_sessionFailureCount reports as zero)
  4. (completion handler is called with correct credentials)
  5. (there is no challenge @error provided)
  6. (there is no challenge @failureResponse provided)
  7.  
  8.  
  9. URLSession:didReceiveChallenge:completionHandler:
  10. (challenge @ prevIoUsFailureCount reports as **zero**!!)
  11. (_sessionFailureCount reports as one)
  12. (completion handler is called with request to cancel challenge)
  13. (there is no challenge @error provided)
  14. (there is no challenge @failureResponse provided)
  15.  
  16. // Finally,the Data Task's completion handler is then called on us.
  17. (the http status code is reported as zero)
  18. (the NSError is reported as NSURLErrorDomain Code=-999 "cancelled")

(NSError还提供了一个NSErrorFailingURLKey,它显示了URL和凭据是正确的.)

欢迎任何建议!

解决方法

您不需要为此执行代理方法,只需在请求上设置授权HTTP头,例如.
  1. NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://whatever.com"]];
  2.  
  3. NSString *authStr = @"username:password";
  4. NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
  5. NSString *authValue = [NSString stringWithFormat: @"Basic %@",[authData base64EncodedStringWithOptions:0]];
  6. [request setValue:authValue forHTTPHeaderField:@"Authorization"];
  7.  
  8. //create the task
  9. NSURLSessionDataTask* task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data,NSURLResponse *response,NSError *error) {
  10.  
  11. }];

猜你在找的iOS相关文章